Vue Core
정의
- approachable - 접근하기 쉬운(프로그레시브 framework특징 - 점진적 도입 가능)
- versatile - 다재다능한
- performant - 효율적인(virtual dom 기반의 효율적 랜더링)
- maintainable - 유지보수 가능한(컴포넌츠 기반 설계로 유지보수에 용이하도록 개발가능)
- testable - 테스트 가능한
특징
- reusable components - 재사용 가능한 컴포넌트들
- reactive - 반응형
기능
선언적 렌더링
DOM 과 데이터를 연결시켜 반응형이 되도록 함
v- 접두어가 붙어있는 속성을 디렉티브 라고함
- 텍스트 보간
-
<div id="app"> {{ message }} </div>
-
- 일회성 보간
-
// 하위 요소들 까지 한번만 렌더링되기 때문에 주의 필요 // 성능 최적화에 좋음 <span v-once> {{ msg }} </span>
-
- 속성 바인딩
-
<!-- 콜론(:) 으로 전달인자 title 사용 --> <span v-bind:title="message"> <!-- 약어 --> <span :title="message">
-
- 원시 HTML
- 이중 중괄호( “{{ }}” ) 는 HTML이 아닌 텍스트로 데이터를 해석하므로 실제 HTML을 출력시 디렉티브 사용
- 데이터 바인딩은 무시됨
- 사용자 입력을 기반으로하는 부분에 사용해선 안됨(XSS 취약점)
-
<span v-html="rawHtml"></span>
- javascript 표현식 사용
- 모든 바인딩 내에서 javascript 표현식 모든기능 지원
- 단일 표현식만 포함 가능
- 전역 객체 사용가능(Math, Date, …)
- 디렉티브 속성값에서 표현식 사용 가능
-
<!-- 아래는 구문입니다, 표현식이 아닙니다. --> {{ var a = 1 }} <!-- 삼항연산자 표현식 사용 --> {{ ok ? 'YES' : 'NO' }}
조건문과 반복문
- 조건문
- v-if, v-show
-
//조건에 부합하지 않을시 렌더링 되지않음 <div v-if="type === 'A'"> A </div> // 항상 렌더링 되고 display속성으로 토글 <div v-show="type === 'B'"> B </div>
- 반복문
- 배열 데이터를 바인딩 하여 표시
- DOM노드를 추적하고 엘리먼트를 재사용, 재정렬 하기위해 고유 key를 제공해야함
- 객체의 속성또한 반복가능
- 단, Object.keys()의 키 나열 순서에 따라 결정되므로 javascript 엔진에 따라 일관적이지 않을 수 있음
-
<ol> <li v-for="todo in todos" v-bind:key="item.id"> {{ toto.text }} ...
사용자 입력 핸들링
- v-on
- vue 인스턴스에서 메소드를 호출하는 이벤트 리스너 추가
-
<button v-on:click="closePopup">팝업 닫기</button> <!-- 약어 --> <button @click="closePopup">팝업 닫기</button>
- 수식어 추가
- .stop - 이벤트 전파 중단
- .prevent - 엘리먼트가 가진 기존의 이벤트을 막음 (ex- v-on:submit.prevent=”realSubmit”)
- .capture - 내부 엘리먼트에서 처리되기전에 현재 엘리먼트에서 처리
- .self - event.target이 엘리먼트 자체인 경우에만 트리거 처리(자식 엘리먼트에서 불가)
- .once - 최대 한번만 트리거 됨
- .passive - 절대 preventDefault 를 호출하지 않을것임을 명시하는 값으로 모바일 환경 성능향상에 도움
- $emit
- 이벤트를 트리거 하는 method
- $emit(eventName)으로 부모 컴포넌트의 리스너에서 감지할 수 있음
-
// 자식 컴포넌트 ... methods:{ clickEvent: function(){ this.$emit('click'); } }
- v-model
- 입력과 앱 상태를 양방향으로 바인딩
- 수식어 추가
- .lazy - input 대신 change 이벤트 이후에 동기화 될수 있도록함
- .number - 사용자 입력이 자동으로 형변환 되도록 하는 수식어
- .trim - 자동 trim
-
<p>{{ message }}</p> <input v-model="message">
컴포넌트
- vue.js에서 부모-자식 컴포넌트 관계는 props는 아래로, events는 위로 라고 요약 할 수 있음
- 독립적이고 재사용할 수 있어 대규모 어플리케이션을 구축할 수 있는 추상적 개념
- 미리 정의된 옵션을 가진 vue 인스턴스
- js
-
// 자식 컴포넌트 Vue.component('todo-item', { //부모 영역의 데이터를 자식 컴포넌트에 상속 가능 props: ['todo'], template: '<li>{{ todo.text }}</li>' })
-
- html
-
<!-- 부모 컴포넌트 --> <ol> <!-- todo-item 컴포넌트에 todo 객체에 item을 할당하여 제공 각 구성 요소에 "key"를 제공해야함 --> <todo-item v-bind:todo="item" v-bind:key="item.id" ></todo-item> </ol>
-
Vue 인스턴스
데이터와 메소드
vue 인스턴스가 생성될때 data 객체에 있는 모든 속성이 vue의 반응형 시스템에 추가됨
data 에 있는 속성들은 인스턴스가 생성될때 존재한 것들만 반응형 시스템에 추가
var vm = new Vue({
data: {
a:1
}
})
- Object.feeze() 로 생성된 변수는 속성의 변경이 불가능
-
var obj = { foo: 'bar' } Object.freeze(obj) var vm = new Vue({ data:obj })
-
- vue 인스턴스 속성, 메소드는 다른 사용자 정의 속성과 구분하기 위해 $ 접두어를 붙여 사용
-
var vueData = vm.$data
-
인스턴스 라이프사이클 훅
각 Vue 인스턴스가 생성되는 단계별로 호출되는 훅
모든 라이프사이클 훅은 this 컨텍스트가 호출하는 vue 인스턴스를 가리키며 호출
options 속성이나 훅에 화살표 함수 사용을 지양하길 권장
-> 화살표 함수는 this를 가지지 않기때문
new Vue({
data: {
a: 1
},
// created hook
created: function () {
console.log('a: ' + this.a)
}
})
- 라이프사이클 훅 종류
- beforeCreate
- vue인스턴스 초기화 직후
- created
- 인스턴스 생성, 반응형 시스템 적용 이후
- 컴포넌트 data에 접근가능
- 보통 이 시점에 서버로 데이터를 요청
- 컴포넌트 내부의 노드를 접근하는것은 불가능
- beforeMount
- 가상DOM은 생성되어있으나 실제 DOM에 mount되지 않은 상태
- mounted
- 실제 DOM에 mounted되고 난 후 동작
- 완전히 mount된 상태를 보장하지 않음
- DOM구조를 조작하는 로직 사용 불가
- beforeUpdate
- data가 변경되어 가상 DOM 에 re-render하기 전에 호출
- updated
- 가상 DOM 렌더링 및 실제 DOM 변경 이후 호출
- 변경된 data가 DOM 에도 적용된 상태
- beforeDestory
- 해당 vue 인스턴스가 해체되기 직전 호출
- 모든 속성에 접근 가능
- 이벤트 리스너 해제 등 처리
- destroyed
- 인스턴스가 해체되고 난 직후 호출
- 인스턴스 속성에 접근 불가
- beforeCreate
computed와 watch
computed
복잡한 javascript 연산을 위한 vue 인스턴스 속성
method에 함수를 정의하는것과 결과는 같지만 computed는 종속 대상을 따라 캐싱 된다는것이 다름
→ 의존성 없는 데이터로만 연산하는경우 절대로 업데이트 되지 않음
// 매번 새로 함수 실행
methods: {
reversedMessage: function(){
return this.message.split('').reverse().join('')
}
},
// 반응형 데이터(this.message)가 변경될 경우만 다시 연산
computed: {
impactMessage: function(){
return `${this.message}!!`
}
}
- setter 함수
- 기본적으로 getter함수만 가지고있지만 setter함수도 사용가능
-
computed:{ fullName: { //getter get: function(){ return this.firstName + ' ' + this.lastName }, //setter set: function(newValue) { ... } } } //vm.fullName = 'Ian Nam'을 실행하면 setter가 //var name = vm.fullName 을 실행하면 getter가 호출됨
watch
감시할 데이터를 지정하고 그 데이터가 바뀌면 실행할 콜백함수
비동기식 또는 시간이 많이 소요되는 작업을 수행시 유용
watch: {
// question 데이터가 변경될때 마다 이 기능이 실행됩니다.
question: function (newQuestion){
this.answer = '입력을 기다리는 중...'
this.debouncedGetAnser()
}
}
Slot
slot은 부모 컴포넌트에서 자식 컴포넌트의 엘리먼트를 지정할때 사용
부모에 따라 자식 컴포넌트가 영향을 받기때문에 컴포넌트 재사용에 용이
자식 컴포넌트에서 부모 컴포넌트로 유연하게 element를 상속받기 위함
// 부모 컴포넌트
<base-layout url="/profile">
<h1 slot="header">--header--</h1>
Your Profile
<template slot="footer">
<p>--footer--</p>
</template>
</base-layout>
// 자식 컴포넌트
<div class="container">
<slot name="header"></slot>
<slot>Default Profile</slot>
<slot name="footer"></slot>
</div>
// 결과
<div class="container">
<h1>--header--</h1>
Your Profile
<p>--footer--</p>
</div>
<base-layout> 템플릿이 <slot>요소를 가지고있지 않다면 그자리에 들어갈 내용은 무시됩니다.
scope
슬롯 안의 데이터 옵션을 사용하고 싶을때
슬롯으로 전달된 속성들을 받기위해
부모 컴포넌트에서의 데이터를 슬롯에 전달하고 싶을때
<slot-example>
<template slot-scope="slotProps">
{{ slotProps.msg }}
</template>
</slot-example>
nextTick
javascript 특성상 비동기적으로 처리되어 DOM 업데이트를 기다리기위해 사용하는 api
<div id="app">
<div v-for="item in list">
<div v-bind:id="bindId(item)"></div>
</div>
</div>
<script>
...
created: function(){
for(var i=0; i<100; i++) {
this._data.list.push(i);
}
// [error-case] 아직 생성되지 않은 dom 을 선택했으므로 에러 발생!!
var dom = document.getElementById('item-0');
dom.style.backgroundColor = 'red';
// [success-case] DOM 업데이트 이후 콜백
this.$nextTick(function(){
var dom = document.getElementById('item-0');
dom.style.backgroundColor = 'red';
})
}
methods: {
bindId: function(item) {
return 'item-' + item;
}
}
</script>
참고자료