컴포넌트 시스템은 vue의 중요한 개념 중 하나로, 작고 독립적이며 재사용할 수 있는 컴포넌트로 구성된 대규모 애플리케이션을 구축할 수 있게 해주는 추상적인 개념이다.
vue에서 component는 미리 정의된 옵션을 가지고 있는 vue 인스턴스다.
대규모 애플리케이션에서는 개발을 보다 쉽게 관리할 수 있도록 전체 앱을 component 단위로 나누는 것이 필수적이다.
모든 vue 앱은 vue함수로 새 vue 인스턴스를 만드는 것부터 시작한다.
var vm = new Vue({
// options
})
vue 인스턴스를 생성할 때 options 객체를 전달해야 한다. 이 옵션을 사용해서 원하는 다양한 동적 이벤트를 구현할 수 있다.
vue 앱은 new Vue
를 통해 만들어진 Root Vue Instance
로 구성되며 선택적으로 중첩이 가능하고, 재사용이 가능한 Component Tree로 구성된다.
Root Instance
└─ TodoList
├─ TodoItem
│ ├─ DeleteTodoButton
│ └─ EditTodoButton
└─ TodoListFooter
├─ ClearTodosButton
└─ TodoListStatistics
new Vue ({
el: ,
template: ,
data: ,
methods: ,
created: ,
watch: ,
// ...
})
el
: 인스턴스가 그려지는 화면의 시작점 (특정 html 태그)template
: 화면에 표시할 요소 (HTML, CSS 등)data
: 뷰의 반응성(Reactivity)이 반영된 데이터 속성methods
: 화면의 동작과 이벤트 로직을 제어하는 메서드created
: 뷰의 lifecycle과 관련된 속성watch
: data에서 정의한 속성이 변화했을 때, 추가 동작을 수행할 수 있게 정의해주는 속성vue에서 제공하는 v-
접두사가 있는 특수 속성으로,
디렉티브의 역할은 표현식의 값이 변경될 때, side effect를 반응적으로 DOM에 적용하는 것이다.
디렉티브 속성 값(value)에 단일 Javascript 표현식을 사용할 수 있다.
v-bind
디렉티브v-if
디렉티브v-on
디렉티브v-model
디렉티브일부 디렉티브는 콜론으로 표시되는 "전달인자"를 사용할 수 있다.
v-bind
디렉티브는 반응적으로 html 속성을 갱신하는데 사용된다.
<a v-bind:href="getUrl">... </a>
위에서 href
는 전달인자로, 엘리먼트의 href
속성을 표현식 url
의 값에 바인드하는 v-bind
디렉티브에게 알려준다.
v-on
디렉티브는 DOM 이벤드를 수식하는데, 전달인자는 이벤트를 받을 이름을 쓴다.
<a v-on:click="doSomething"> ... </a>
Javascript 표현식을 대괄호로 묶어서 디렉티브의 arguments로 사용할 수 있다.
<a v-bind:[attributeName]="url"> ... </a>
attributeName
은 자바스크립트 형식으로 동적 변환되어, 그 변환 결과가 전달인자의 최종적인 값(value)로 사용된다. vue 인스턴스에 href
라는 값(value)을 가진 attributeName
데이터 속성을 가진 경우, 이 바인딩은 v-bind:href
와 동등한 의미를 갖는다.
<a v-on:[eventName]="doSomething"> ... </a>
eventName
의 값(value)이 focus
이면, v-on[eventName]
은 v-on:focus
와 동등한 의미를 갖는다.
수식어는 점으로 표시되는 특수 접미사로, 디렉티브를 특별한 방법으로 바인딩을 해야 함을 나타낸다.
<form v-on:submit.prevent="onSubmit"></form>
.prevent
수식어는 트리거된 이벤트에서 event.preventDefault()
를 호출하도록 v-on
디렉티브에게 알려준다.
v-
접두사는 템플릿의 vue 특정 속성을 식별하기 위한 시각적인 신호 역할을 한다.
v-
접두사의 필요성이 떨어지는 경우, v-bind
, v-on
의 약어는 아래와 같다.
<!-- 전체 문법 -->
<a v-bind:href="url"> ... </a>
<!-- 약어 -->
<a :href="url"> ... </a>
<!-- shorthand with dynamic argument (2.6.0+) -->
<a :[key]="url"> ... </a>
<!-- 전체 문법 -->
<a v-on:click="doSomething"> ... </a>
<!-- 약어 -->
<a @click="doSomething"> ... </a>
<!-- shorthand with dynamic argument (2.6.0+) -->
<a @[event]="doSomething"> ... </a>
데이터 바인딩은 element의 클래스 목록과 inline-style을 조작하기 위해 일반적으로 사용된다!
이 두 속성은 v-bind를 사용해서 처리할 수 있다.
표현식으로 최종 문자열을 계산하면 되는데, 표현식은 문자열 이외에 객체 / 배열도 이용할 수 있다.
클래스를 동적으로 toggle하기 위해, v-bind:class
에 객체를 전달할 수 있다.
isActive
의 true 속성인 경우, active
클래스가 toggle되는 예시
<div v-bind:class="{active: isActive}"
v-bind:class
디렉티브는 일반 class 속성과 공존할 수 있다.
<div
class="static"
v-bind:class="{active: isActive, 'text-danger': hasError}"
>
</div>
<!-- 아래 적용 후 렌더링 결과 -->
<div class="static active"></div>
<!-- 인스턴스 -->
var vm = new Vue({
data: {
isActive: true,
hasError: false
}
})
바인딩 된 객체는 inline이 아니어도 되고, 객체를 반환하는 computed 속성에도 바인딩을 할 수 있다.
<div v-bind:class="classObject"></div>
data: {
isActive: true,
error: null
}
computed: {
classObject: function(){
return {
active: this.isActive && !this.error,
'text-danger': this.error && this.error.type === 'fatal'
}
}
}
배열을 v-bind:class
에 전달하여 클래스 목록을 지정할 수 있다.
<div v-bind:class="[activeClass, errorClass]"></div>
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
// 렌더링 결과
<div class="active text-danger"></div>
사용자 정의 컴포넌트로 class 속성을 사용하면, 클래스가 컴포넌트의 루트 엘리먼트에 추가된다. 이 엘리먼트는 기존 클래스를 덮지 않는다.
Vue.component('my-component', {
template: '<p class="foo bar">Hi</p>'
})
<my-component class="baz boo"></my-component>
// 렌더링 결과
<p class="foo bar baz boo">Hi</p>
v-bind:style
객체 구문은 매우 직설적이다.
거의 CSS처럼 보이지만 Javascript 객체로, 속성 이름에 camelCase와 kebab-case를 사용할 수 있다.
<div v-bind:style="styleObject"></div>
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
v-bind:style
에 대한 배열 구문은, 같은 스타일의 엘리먼트에 여러 개의 스타일 객체를 사용할 수 있게 한다.
<div v-bind:style="[baseStyle, overridingStyle]"></div>
v-bind:style
에 브라우저 벤더프리픽스에 필요한 css속성 (예: display: flex)을 사용하면 vue는 자동으로 감지하여 스타일을 적용한다.
message
속성 값(value)으로 대체되고, 데이터 객체의 message
값이 변경될 때마다 갱신된다.<span>매세지는 {{ message }} 이다.</span>
v-html
디렉티브를 사용한다.<p>Using Mustache: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
vueJS는 모든 데이터 바인딩 내에서 Javascript 표현식의 모든 기능을 지원한다.
단, 각 바인딩에 하나의 단일 표현식만 포함될 수 있으므로, 조건문이나 선언은 하지 않는다!
{{ number + 1 }}
{{ ok ? 'yes' : 'no' }}
{{ message.split('').reverse().join('') }}
<div v-bind:id="'list-' + id"></div>
<!-- 아래는 표현식이 아닌 구문이므로 사용하지 않는다. -->
{{ var a = 1 }}
<!-- 조건문은 작동하지 않기에, 삼항 연산자를 사용한다. -->
{{ if (ok) { return message } }}
vue 인스턴스가 생성될 때 data 객체에 있는 모든 속성이 vue의 반응형 시스템에 추가된다.
각 속성 값이 변경될 때, vue가 반응해서 새로운 값과 일치하도록 업데이트 된다.
// 데이터 객체
var data = { a: 1 }
// vue 인스턴스에 데이터 객체를 추가
var vm = new Vue({
data: data
})
// 인스턴스에 있는 속성은 원본 데이터에 있는 값을 반환
vm.a === data.a // => true
// 인스턴스에 있는 속성값을 변경하면 원본 데이터에도 영향을 미친다.
vm.a = 2
data.a // => 2
// ... 반대로 마찬가지입니다.
data.a = 3
vm.a // => 3
data에 있는 속성은 인스턴스가 변경될 때 존재한 것들만 반응형이고, b
라는 새로운 속성을 추가하면 b
를 변경해도 화면이 갱신되지 않는다. 때문에 필요한 속성이 있거나, 빈 값으로 시작해야 한다면 애초에 초깃값을 지정해서 시작하는게 좋다. (변수 선언)
vm.b = 'hi // 화면 갱신 안됨
var vm = new Vue ({
data: {
newTodoText: '',
visitCount: 0,
hideCompletedTodos: false,
todos: [],
error: null
}
}