티스토리 뷰
(공부 책 : Vue.js Quick Start )
컴포넌트 조합
컴포넌트들은 부모 - 자식 관계로 트리 구조를 형성합니다. (부모가 자식을 포함)
속성(Props)을 통해서 주로 단방향으로 부모 컴포넌트에서 자식 컴포넌트로 정보를 전달합니다.
양방향도 가능하나 코딩 복잡도가 높아지고 유지 보수에 어려움이 있어 권장하지 않습니다.
반면, 자식 컴포넌트는 부모 컴포넌트로 이벤트를 발신할 수 있습니다.
자식 컴포넌트에서 이벤트를 정의하고 이를 발생시키면 부모 컴포넌트에서 이벤트 핸들러 메소드가 호출토록 합니다.
즉, 부모-자식 컴포넌트 관계는 props는 아래로, events 위로 라고 요약 할 수 있습니다.
부모는 props를 통해 자식에게 데이터를 전달하고 자식은 events를 통해 부모에게 메시지를 보냅니다.
대부분의 Vue 인스턴스의 옵션(methods, computed, watch 등)을 컴포넌트에서 사용가능 합니다만
data 옵션은 기존과 같은 방식으로 사용하지 않습니다.
컴포넌트 기반으로 개발하면 data옵션은 컴포넌트 로컬 상태를 관리하기 위한 용도로만 사용합니다.
또한 하나의 컴포넌트를 여러 번 사용할 경우 모두 다른 상태 정보를 가져야 합니다.
기존처럼 작성할 경우 객체가 참조형 값이므로 모두 동일한 값을 참조하게 되어 다른 상태 정보를 갖지 못하게 됩니다.
그러므로 컴포넌트에서 data 옵션은 반드시 함수로 작성하고 함수 내부에서 객체를 리턴하는 방식으로 작성합니다.
1. 컴포넌트의 작성
컴포넌트 메서드는 다음과 같습니다.
Vue.component(tagename, options)
tagname : 컴포넌트를 사용할 태그명 ( 대소문자 구분 X )
options : 컴포넌트에서 랜더링할 templet 등을 지정
<body>
<script type="text/javascript">
Vue.component('hello-component', {
template: '<div>Hello World!</div>'
})
</script>
<div id="app">
<hello-component></hello-component>
</div>
<script type="text/javascript">
var v = new Vue({
el: '#app'
})
</script>
</body>
위 예제처럼 template 옵션에 적용할 수 있는 값을 인라인 템플릿 방식으로 템플릿 문자열을 직접 지정해도 되지만,
템플릿 문자열을 포함하고 있는 <template> 태그, <script type="text/x-template"> 태그의 id를 지정해도 됩니다.
<template id="helloTemplate">
<div>Hello World!</div>
</template>
<script type="text/javascript">
Vue.component('hello-component', {
template: '#helloTemplate'
})
</script>
<script type="text/x-template" id="helloTemplate">
<div>Hello World!</div>
</script>
<script type="text/javascript">
Vue.component('hello-component', {
template: '#helloTemplate'
})
</script>
2. DOM 템플릿 구문 작성 시 주의사항
(1) HTML 요소들은 자식 요소를 포함시킬 수 있는 요소들이 정해져 있는 경우가 있습니다.
이 사항을 브라우저가 구문 분석으로 수행하는데 Vue 컴포넌트가 사용되면 때때로 오류가 발생하기도 합니다.
<script type="text/javascript">
Vue.component('option-component', {
template: '<option>hello</option>'
})
</script>
<body>
<div id="app">
<select>
<option-component></option-component>
<option-component></option-component>
</select>
</div>
</body>
<script type="text/javascript">
var v = new Vue({
el: '#app'
})
</script>
위 코드는 <select> 태그 안에서 작성한 option-component 컴포넌트를 사용하고 있습니다.
하지만 <select> 태그 안에 <option-component>라는 태그를 사용할 수 있다라는 것이 브라우저에 등록되어있지 않습니다.
브라우저는 이 태그들을 구문 분석하는 작업 먼저 수행한 후 Vue 컴포넌트를 랜더링합니다.
구문 분석 단계에서 DOM 요소가 올바르지 않다 판단하기에 실행시 랜덩링하지 못하는 문제가 발생합니다.
이를 해결하기 위해 is 특성을 이용합니다.
<body>
<div id="app">
<select>
<option is="option-component"></option>
<option is="option-component"></option>
</select>
</div>
</body>
is 특성을 이용하면 문제없이 랜더링되는 것을 확인할 수 있습니다. 혹은
<script type="text/x-template"></script> 안에
<select>
<option-component></option-component>
<option-component></option-component>
</select>
코드가 들어가거나 .vue 확장자를 사용하는 단일 파일 컴포넌트를 작성하는 경우 is 특성을 이용하지 않아도 랜더링이 됩니다.
(2) 템플릿 문자열 안에서 루트 요소는 하나여야 합니다.
만약 템플릿 내부에서 여러 요소를 작성해야 한다면 <div>등으로 감싸주어 하나의 루트 요소가 되게끔 해야합니다.
그렇지 않으면 정상적으로 랜더링되지 않기에 주의할 필요가 있습니다.
<template id="helloTemplate">
<div>Hello</div>
<div>World!</div>
</template>
<!-- 하나의 루트 요소로 변경해주어야한다. -->
<template id="helloTemplate">
<div>
<div>Hello</div>
<div>World!</div>
</div>
</template>
3. DOM 템플릿 구문 작성 시 주의사항
컴포넌트 내부의 로컬 상태 정보를 저장하기 위해 data 옵션을 사용할 수 있습니다.
하지만 이제까지처럼 data 옵션에 객체를 직접 지정하면 오류가 발생합니다.
<template id='timeTemplate'>
<div>
<span>{{now}}</span>
<button v-on:click="timeClick">현재 시간</button>
</div>
</template>
<script type="text/javascript">
Vue.component('time-component', {
template: '#timeTemplate',
data: {
now: 0
},
methods: {
timeClick: function(e) {
this.now = (new Date()).getTime();
}
}
})
</script>
위 예제를 실행해보면
에러가 나는걸 확인할 수 있습니다.
정상적으로 렌더링되려면 data 옵션에 함수가 주어져야 합니다.
정확히는 함수가 호출되어 리턴된 객체가 data 옵션에 주어져야 합니다.
위 코드에서 data 부근을
data : function() {
return { now : 0 }
},
와 같이 바꾸면 정상적으로 작동되는것을 확인할 수 있습니다.
이와 같이 data 옵션에 함수를 지정하는 이유는 동일한 컴포넌트가 여러 번 사용되더라도
함수가 호출될 때마다 새로이 만들어진 객체가 리턴되기 때문입니다.
'Vue' 카테고리의 다른 글
Vue-CLI 도구 (0) | 2021.09.28 |
---|---|
Vue.js 컴포넌트 기초 - 2 (0) | 2021.06.29 |
Vue.js 스타일 (0) | 2021.03.25 |
Vue.js 이벤트 처리 (0) | 2021.02.25 |
Vue 인스턴스 (0) | 2021.01.29 |