[선언적 렌더링]
Vue.js의 핵심은 간단한 템플릿 구문을 사용해 선언적으로 DOM에 데이터를 렌더링 하는것.
data와 DOM이 연결되어 모든것이 반응형(reactive)하다. element 속성을 바인딩 하는것도 가능
[디렉티브]
v-bind 속성 디렉티브(e.g. <a :href="url">)라고 한다. 디렉티브는 Vue에서 제공하는 특수 속성인 v- 접두어가 붙어있으며 렌더링된 DOM에 특수한 반응형 동작을 한다.
v-if 속성을 통해서 엘리먼트 토글이 가능하다. v-for 디렉티브는 배열의 데이터를 사용해 목록을 표시한다. v-model 디렉티브는 앱 상태를 양방향으로 바인딩한다.
v-on 디렉티브(e.g. <a @click="doSomething">...</a>)를 사용하여 Vue 인스턴스에 메소드를 호출하는 이벤트 리스터를 첨부할 수 있다. DOM을 건드리지 않고 앱의 상태를 업데이트한다. 모든 DOM 조작은 Vue에 의해 처리되며 작성한 코드는 기본 로직에만 초점을 맞춘다.
<div id="app-5"> <p>{{ message }}</p> <button v-on:click="reverseMessage">메시지 뒤집기</button> </div>
var app5 = new Vue({ el: "#app-5", data: { message: '안녕하세요! Vue.js!' }, methods: { reverseMessage: function() { this.message = this.message.split('').reverse().join('') } } });
[컴포넌트 트리]
컴포넌트 시스템은 Vue의 중요한 개념이다. 작은 단위 기능으로 동작하며 재사용할 수 있는 컴포넌트로 구성된 응용애플리케이션을 작성할 수 있게 해준다.
Vue에서 컴포넌트는 미리 정의된 옵션을 가진 Vue 인스턴스다. Vue에서 컴포넌트를 등록하는 방법이다.
Vue.component('todo-item', { template: '<li>할일 항목 하나입니다.</li>' })
이제 다른 컴포넌트의 템플릿에서 이 컴포넌트를 사용할 수 있다. 부모 영역의 데이터를 자식 컴포넌트에 주입 즉, prop을 전달받을수 있도록 컴포넌트 정의를 수정하는 것도 가능하다.
<div id="app-7"> <ol> <!-- 각 구성 요소에 "키"를 제공해야 함. --> <todo-item v-for="item in groceryList" v-bind:todo="item" v-bind:key="item.id"> </todo-item> </ol> </div>
Vue.component('todo-item', { props: ['todo'], template: '<li>{{ todo.text }}</li>' }) var app7 = new Vue({ el: '#app-7', data: { groceryList: [ { id: 0, text: 'Vegetables' }, { id: 1, text: 'Cheese' }, { id: 2, text: 'Whatever else humans are supposed to eat'} ] } })
부모 컴포넌트에 영향을 주지 않으면서 <todo-item> 컴포넌트를 더 복잡한 템플릿과 로직으로 더욱 향상시킬 수 있게된다.
[Vue 인스턴스 생성]
모든 Vue앱은 Vue 함수로 신규 Vue 인스턴스를 만드는 것부터 시작된다.
var vm = new Vue({ // 옵션 })
Vue 인스턴스를 인스턴스화할 때는 데이터, 템플릿, 마운트할 엘리먼트, 메소드, 라이프사이클 콜백등의 옵션을 포함할 수 있는 options 객체를 전달해야 한다. Vue 생성자는 미리 정의된 옵션으로 재사용 가능한 컴포넌트 생성자를 생성하도록 확장될 수 있다.
대개 템플릿에서 사용자 지정 엘리먼트로 선언적으로 작성하는 것이 권장된다. 모든 Vue 컴포넌트는 본질적으로 확장된 Vue 인스턴스이다.
Vue 인스턴스 option 중 data가 변경되면 화면은 다시 렌더링된다. data에 있는 속성들은 인스턴스가 생성될때 존재한 것들만 반응형이 된다. 유일한 예외는 Object.freeze()를 사용하는 경우다. 이는 기존 속성이 변경되는 것을 막아 반응성 시스템이 추적할 수 없다는 것을 의미한다.
var obj = { foo: 'bar' } Object.freeze(obj) new Vue({ el: '#app', data: obj })
내부적으로 Vue는 템플릿을 가상 DOM 렌더링함수로 컴파일한다. 앱상태가 변경될때 최소한으로 DOM 변경처리를 하려는 의도를 가지고 있다.
Vue가 v-for에서 렌더링된 엘리먼트 목록을 갱신할때 기본적으로 "in-place patch" 전략을 사용한다. 데이터 항목의 순서가 변경된 경우 항목의 순서와 일치하도록 DOM 요소를 이동하는 대신 Vue는 각 요소를 적절한 위치에 패치하고 해당 인덱스에서 렌더링할 내용을 반영하는지 확인한다.
Vue에서 DOM 노드들을 추적하고 기존 엘리먼트를 재사용/재정렬하기 위해서 v-for의 각 항목들에 고유한 key 속성을 제공해야 한다. 속성처럼 작동하기 때문에 v-bind를 사용하여 동적 값에 바인딩 해야 한다.
<div v-for="item in items" :key="item.id"> <!-- content --> </div>
반복되는 DOM 내용은 v-for에 key를 추가하는 것이 좋다. key는 Vue가 노드를 식별하는 일반적인 메커니즘이기 때문에 v-for와 특별히 연관되지 않는 다른 용도로 사용된다. Vue.js 2,2.0 이상부터는 v-for는 key가 필수이다.
Vue는 배열에 대해 다음과 같은 변경 변경사항을 감지할 수 없다.
인덱스로 배열에 있는 항목을 직접 설정하는 경우 (vm.items[indexOfItem] = newValue)
// 해결책1. Vue.set Vue.set(example1.items, indexOfItem, newValue) // 해결책2. Array.prototype.splice example1.items.splice(indexOfItem, 1, newValue)
모던 Javascript의 한계로 Vue는 속성 추가/삭제를 감지하지 못한다.
var vm = new Vue({ data: { a: 1 // 반응형 } }) vm.b = 2 // 반응형이 아님.
Vue는 이미 만들어진 인스턴스에 새로운 root level에 반응형 속성을 동적으로 추가하는것을 허용하지 않지만, Vue.set(object, key, value) 메소드를 사용하여 중첩된 객체에 반응형 속성을 추가할 수 있다.
var vm = new Vue({ data: { userProfile: { name: 'Anika' } } }) // userProfile 객체에 새로운 속성 age 추가 Vue.set(vm.userProfile, 'age', 27) // 인스턴스 메소드 vm.$set 사용도 가능. Vue.set의 별칭 vm.$set(this.userProfile, 'age', 27) // Object.assign(), _.extend()를 사용하여 기존 객체에 새속성 할당도 가능 // 이경우, 두 객체의 속성을 사용해 새 객체를 만들어야함 Object.assign(this.userProfile, { age: 27, favoriteColor: 'Vue Green' }) this.userProfile = Object.assign({}, this.userProfile, { age: 27, favoriteColor: 'Vue Green' })
컴포넌트에는 자체 범위가 분리되어있기때문에 컴포넌트에 데이터를 자동으로 전달하지는 않는다. 반복할 데이터를 컴포넌트로 전달하려면 props를 사용해야 한다. 데이터의 출처를 명확히하면 다른 상황에서 컴포넌트를 재사용할 수 있다.
<div id="todo-list-example"> <input v-model="newTodoText" @keyup.enter="addNewTodo" placeholder="Add a todo" > <ul> <li is="todo-item" v-for="(todo, index) in todos" :key="todo.id" :title="todo.title" // prop 넘기는 방법 @remove="todos.splice(index, 1)" </ul> </div>
Vue.component('todo-item', { template: '\ <li>\ {{ title }}\ <button @click="$emit(\'remove\')">X</button>\ </li>\ ', props: ['title'] }) new Vue({ el: '#todo-list-example', data: { newTodoText: '', todos: [ { id: 1, title: 'Do the dishes', }, { id: 2, title: 'Take out the trash', }, { id: 3, title: 'Now the lawn' } ], nextTodoId: 4 }, methods: { addNewTodo: function() { this.todos.push({ id: this.nextTodoId++, title: this.newTodoText }) this.newTodoText = '' } } })
'프로그래밍(TA, AA) > 자바스크립트' 카테고리의 다른 글
[Vue.js] 공식 가이드 문서 요약 (3) - 플러그인 (0) | 2018.12.25 |
---|---|
[Vue.js] 공식 가이드 문서 요약 (2) - 컴포넌트 (0) | 2018.12.22 |
[자바스크립트] 압축(Minify) / 난독화(Uglify) (1) | 2018.03.20 |
[자바스크립트] strict mode를 사용해야 하는 이유 (0) | 2018.03.08 |
ECMAScript® 2015 Language Specification (0) | 2017.11.27 |