Tempo Di Valse

[Vue.js] Root Component 에 Prop 전달하기 본문

개발/Web

[Vue.js] Root Component 에 Prop 전달하기

TempoDiValse 2022. 4. 20. 18:04

A 와 B 컴포넌트가 있고 B 컴포넌트는 A 컴포넌트에 속해있을 때, A 에서 B 의 기본값을 정의해 줄 때가 있다.

 

그럴 때에는 보통 다음의 프로세스를 따라 정의를 하게 된다.

1. B 컴포넌트에 props 를 정의한다.
2. A 컴포넌트에서 B 컴포넌트에 정의한 props 의 name 값으로 데이터를 전달한다.

이 프로세스를 소스로 옮기게 된다면,

<A>
    <B></B>
</A>

인 경우에 B 컴포넌트에

// B.vue

<template>
</template>

<script>
export default {
    name: "B",
    props: [ "value" ],
}
</script>

props 에 value 라는 이름으로 property 를 추가했으며 A 에서는,

<A>
    <B value="test"></B>
</A>

value 이름을 가지고 데이터를 넣어주게 된다. 만약, 일반 값이 아닌 변수를 넘겨주게 된다면 그냥 value 가 아니라 :value 를 사용하게 될 것이다.

 

여기까지는 기본적인 Vue 의 props 에 대한 정의 였다. 하지만, 이 내용은 최상위 컴포넌트 에서는 이뤄지지 않는다.

 

최상위 컴포넌트 는 Vue 의 시작점 이라고 이야기할 수 있다. 최상위 컴포넌트의 역할은 기본적으로는 Vue 를 생성하고 HTML 어느 부분에 렌더 해줄 지 정해준다. 그 외에 vue-router 나 기타 플러그인을 configure 하는 용도로 사용되는데, 파일도 *.vue 파일이 아닌 일반 *.js 파일로 되어있다.

 

여기서, "최상위 컴포넌트에 값을 넘겨줄 필요가 있을까?" 생각할 수도 있을 것 같은데, 개발하다보면 초가 설정값에 맞게 데이터를 뿌려줘야 할 때가 생기기 떄문에 그럴 경우에는 최상위 컴포넌트에다가 값을 미리 던져줘서 해당 값에 맞게 적절하게 보여주도록 구현해야한다. 그러나 일반적인 방법으로는 념겨주지 못하고 있다.

 

최상위 컴포넌트에 값을 넘겨주는게 외않되냐... 하면, 가장 큰 이유는 "Vue 밖" 이다. 보통, <div id="app"></div> 이고 여기에다가 Vue 의 컴포넌트를 구현해주는데, Vue el 을 통해 위치를 지정해서 해당 위치에 Vue 를 적용하는 것이지 겉의 <div> 레이어를 감싸주는 것이 아니다. 그래서 최상위 컴포넌트에 props 를 정의한다 해도 Vue 에서는 해당 값을 가져올 수 없다 (아마 undefined 만 뜰 것이다).

 

그래도 넘겨주는 방법이 있나니, 방법은 바로 DOM 의 dataset 을 이용하는 방법이다. 그럼 구현에 대해 알아보도록 하자.


먼저, HTML 의 <div> 레이어를 다음처럼 바꿔보도록 하자.

<div id="app" data-value="test"></div>

추가된 것은 'data-' Prefix 가 있는 속성이다. 'data' 가 붙은 속성은 일반적으로 사용하는 속성은 아니고 태그 속성에 직접적인 영향을 끼치진 않지만, 해당 태그에 의미있는 값이 필요한 경우에는 사용되는데 자세한 정의는 다음의 링크에서 확인해보도록 한다.

 

데이터 속성 사용하기 - Web 개발 학습하기 | MDN

HTML5 특정 요소와 연관되어 있지만 확정된 의미는 갖지 않는 데이터에 대한 확장 가능성을 염두에 두고 디자인되었습니다. data-* 속성은 표준이 아닌 속성이나 추가적인 DOM 속성, Node.setUserData

developer.mozilla.org

'data' 가 붙은 속성은 JS 를 통해서 해당 태그에 접근하게 되면 dataset 이라는 것을 통해서 접근을 할 수 있다. 그래서 방금 전에 바꿨던 값을 JS 에서 확인하게 된다면,

const el = document.getElementById('app');

console.log(el.dataset.value);
// => test

dataset 에서 뒤에 속성 이름만 작성 하면 바로 접근을 할 수 있게된다. 그냥 '.'만 찍어서 접근할 수 있는 걸로 느끼는 사람도 있겠지만 dataset 은 단순하게 Key-Value 형태로 되어 있다고 생각할 수도 있다.

 

그 다음으로는, 최상단 컴포넌트가 정의된 파일을 열어본다. 나의 경우에는 app.js 라는 파일이 파일의 최상단을 담당하고 있다.

import AComponent from './AComponent'

const el = document.getElementById('app')

new Vue({
    el: el, // CSS Selector 가 아니어도 객체로 타겟을 줄 수 있다.
    props: [ "value" ],
    propsData: { ...el.dataset },
    render: (h) => h(AComponent)
})

보통 el 값에는 CSS Selector 를 주긴 하지만, 이 경우에는 ID 가 app 으로 지정되어있는 태그의 데이터도 함께 쓸 것이기 때문에 JS 를 통해 태그 객체를 가져와서 최상위 컴포넌트에 전달을 시켜주었다. 그리고 props 에 <div> 레이어에 정의해 놓은 것과 같이 value 의 Property 를 추가해주었다. 여기서 가장 중요한 부분인 propsData 에 dataset 값을 넣어주는데, 여기서 el.dataset 앞에 붙어있는 3개의 점이 포인트이다.물론 저 기법을 쓰지 않고 propsData: el.dataset 로 써도 상관은 없지만 { ...el.dataset } 과는 사용상의 큰 차이가 있기 때문에 { ...el.dataset } 을 사용하기로 한다. '...'에 대한 설명은 Spread 라고 이야기 하는데, 자세한 것은 다음 링크를 확인하도록 한다.

 

전개 구문 - JavaScript | MDN

전개 구문을 사용하면 배열이나 문자열과 같이 반복 가능한 문자를 0개 이상의 인수 (함수로 호출할 경우) 또는 요소 (배열 리터럴의 경우)로 확장하여, 0개 이상의 키-값의 쌍으로 객체로 확장시

developer.mozilla.org

이제 mounted 를 추가하여 제대로 불러오는 지 확인을 해보도록 한다.

import AComponent from './AComponent'

const el = document.getElementById('app')

new Vue({
    el: el, // CSS Selector 가 아니어도 객체로 타겟을 줄 수 있다.
    props: [ "value" ],
    propsData: { ...el.dataset },
    render: (h) => h(AComponent),
    mounted(){
        console.log(this.value)
    }
})

제대로 작성했다면 태그에다가 썼던 'test' 라는 글자가 브라우저 콘솔에 출력이 될 것이다.


만약, 바로 AComponent 에 props 를 전달하고자 한다면, render 의 값을 조금 바꾸면 된다.

import AComponent from './AComponent'

const el = document.getElementById('app')

new Vue({
    el: el, // CSS Selector 가 아니어도 객체로 타겟을 줄 수 있다.
    props: [ "value" ],
    propsData: { ...el.dataset },
    render: (h) => h(AComponent, {
        props: this.$props
    })
    /** 만약 최상단에서는 쓸일이 없고 컴포넌트로 바로 패스한다면,
    render: (h) => h(AComponent, {
        props: el.dataset
    })
    */
})

해당 방법은 최상단 컴포넌트에 정의된 props 데이터들을 전부 AComponent 에 패스하도록 작성한 것이다.

반응형
Comments