npm install vue-cli -g
vue init webpack-simple or vue init webpack
npm install
npm run dev
npm run build
뷰 인스턴스는 뷰로 화면을 개발하기 위해 필수적으로 생성해야 하는 기본 단위이다.
new Vue({
...
});
<div id="app">
{{message}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
<script>
new Vue({
el:'#app',
data:{
message: 'Hello Vue.js!'
}
});
</script>
el: '#app'부분은 뷰로 만든 화면이 그려지는 시작점이며
화면을 렌더링 할때 화면이 그려질 위치의 돔 요소를 지정해주어야한다.
data:{}에서 미리 정의되어있는 속성을 사용한다.
Vue 인스턴스는 크게 생성(create)되고, DOM에 부착(mount)되고, 업데이트(update)되며, 없어지는(destroy) 4가지 과정을 거치게 됩니다.
이 과정에서 Vue는 각각의 단계에서, Vue를 사용하는 사람들을 위해 훅(Hook)을 할 수 있도록 API를 제공합니다. 일반적으로 많이 사용하는 종류로는 beforeCreate, created, beforeMount, mounted, beforeUpdate, updated, beforeDestroy, destroyed가 있습니다.
이름처럼 가장 먼저 실행되는 beforeCreate훅입니다. Vue 인스턴스가 초기화 된 직후에 발생됩니다. 컴포넌트가 DOM에 추가되기도 전이어서 this.$el에 접근할 수 없습니다. 또한 data, event, watcher에도 접근하기 전이라 data, methods에도 접근할 수 없습니다.
created훅에서는 data를 반응형으로 추적할 수 있게 되며 computed, methods, watch 등이 활성화되어 접근이 가능하게 됩니다. 하지만 아직까지 DOM에는 추가되지 않은 상태입니다.
data에 직접 접근이 가능하기 때문에
, 컴포넌트 초기에 외부에서 받아온 값들로 data를 세팅해야 하거나 이벤트 리스너를 선언해야 한다면 이 단계에서 하는 것이 가장 적절합니다.
DOM에 부착하기 직전에 호출되는 beforeMount훅입니다. 이 단계 전에서 템플릿이 있는지 없는지 확인한 후 템플릿을 렌더링 한 상태이므로, 가상 DOM이 생성되어 있으나 실제 DOM에 부착되지는 않은 상태입니다.
일반적으로 가장 많이 사용하는 mounted훅입니다. 가상 DOM의 내용이 실제 DOM에 부착되고 난 이후에 실행되므로, this.$el을 비롯한 data, computed, methods, watch 등 모든 요소에 접근이 가능합니다
.
하지만 자식 컴포넌트가 서버에서 비동기로 데이터를 받아오는 경우처럼, 부모의 mounted훅이 모든 자식 컴포넌트가 마운트 된 상태를 보장하지는 않습니다. 따라서 이때는 this.$nextTick을 이용한다면, 모든 화면이 렌더링 된 이후에 실행되므로 마운트 상태를 보장할 수 있습니다
.
컴포넌트에서 사용되는 data의 값이 변해서, DOM에도 그 변화를 적용시켜야 할 때가 있습니다. 이 때, 변화 직전에 호출되는 것이 바로 beforeUpdate훅입니다. 변할 값을 이용해 가상 DOM을 렌더링하기 전이지만, 이 값을 이용해 작업할 수는 있습니다. 이 훅에서 값들을 추가적으로 변화시키더라도 랜더링을 추가로 호출하지는 않습니다.
가상 DOM을 렌더링 하고 실제 DOM이 변경된 이후에 호출되는 updated훅입니다.
변경된 data가 DOM에도 적용된 상태입니다. 만약 변경된 값들을 DOM을 이용해 접근하고 싶다면, updated훅이 가장 적절합니다.
다만 이 훅에서 data를 변경하는 것은 무한 루프를 일으킬 수 있으므로 이 훅에서는 데이터를 직접 바꾸어서는 안됩니다.
mounted훅과 마찬가지로, this.$nextTick을 이용해, 모든 화면이 업데이트 된 이후의 상태를 보장할 수 있습니다.
해당 인스턴스가 해체되기 직전에 beforeDestroy훅이 호출됩니다. 아직 해체되기 이전이므로, 인스턴스는 완전하게 작동하기 때문에 모든 속성에 접근이 가능합니다. 이 단계에서는 이벤트 리스너를 해제하는 등 인스턴스가 사라지기 전에 해야할 일들을 처리하면 됩니다.
인스턴스가 해체되고 난 직후에 destroyed훅이 호출됩니다. 해체가 끝난 이후기 때문에, 인스턴스의 속성에 접근할 수 없습니다. 또한 하위 Vue 인스턴스 역시 삭제됩니다.
참고:
https://wormwlrm.github.io/2018/12/29/Understanding-Vue-Lifecycle-hooks.html
컴포넌트를 등록하는 방법은
1. 전역 컴포넌트 - 여러 인스턴스에서 공통으로 사용 가능
2. 지역 컴포넌트 - 특정 인스턴스에서만의 유효한 범위
<div id="app">
<button>컴포넌트 등록</button>
<my-component></my-componont>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
<script>
Vue.component('my-component',{
template: '<div>전역 컴포넌트가 등록되었습니다!</div>'
});
new Vue({
el:'#app',
});
</script>
전역 컴포넌트가 화면에 나타나기까지
1. 뷰 라이브러리 파일 로딩 ->
2. 뷰 생성자로 컴포넌트 등록(Vue.component())->
3. 인스턴스 객체 생성(옵션 속성 포함)->
4. 특정 화면 요소에 인스턴스 부착->
5. 인스턴스 내용 변환(등록된 컴포넌트 내용도 변환
my-component가 <div>
로 변환)->
6. 변환된 화면 요소를 사용자가 최종 확인
var cmp = {
//컴포넌트 내용
// data:{},
// methods:{},
template: '<div>지역 컴포넌트가 등록되었습니다!</div>'
}
new Vue({
el: '#app',
components:{
'my-local-component': cmp
}
});
<div id="app">
<h3>첫번째 인스턴스 영역</h3>
<my-global-component></my-global-component>
<my-local-component></my-local-component>
</div>
<hr></hr>
<div id="app2">
<h3>두번째 인스턴스 영역</h3>
<my-global-component></my-global-component>
<my-local-component></my-local-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>
<script>
Vue.component('my-global-component',{
template:'<div>전역 컴포넌트 입니다.</div>'
});
var cmp = {
//컴포넌트 내용
// data:{},
// methods:{},
template: '<div>지역 컴포넌트가 등록되었습니다!</div>'
}
new Vue({
el: '#app',
components:{
'my-local-component': cmp
}
});
new Vue({
el: '#app2'
})
</script>
위의 코드의 결과는 첫번째에는 전역, 지역 컴포넌트가
정상적으로 나타났으나, 두번재에는 전역 컴포넌트만 나타나고
지역컴포넌트는 나타나지 않는다.
전역 컴포넌트는 인스턴스를 새로 생성할때마다 인스턴스에 components 속성으로 등록할 필요없이 한번만 등록한다면 어느 인스턴스에서든지 사용이 가능하다, 하지만 지역컴포넌트는 새 인스턴스를 생성할때마다 등록해주어야한다.
Vue.component('my-global-component',{
template:'<div>전역 컴포넌트 입니다.</div>'
});
var cmp1 = {
template: '<div>첫번째 지역 컴포넌트 : {{cmp1Data}}</div>',
data(){
return {
cmp1Data : 100
}
}
}
var cmp2 = {
template: '<div>두번째 지역 컴포넌트 : {{cmp2Data}}</div>',
data(){
return{
cmp2Data : cmp1.data.cmp1Data
}
}
};
new Vue({
el: '#app',
components:{
'my-component1': cmp1,
'my-component2': cmp2,
}
});
뷰에서는 같은 웹페이지라도 데이터를 공유할수가없다.
컴포넌트마다 자체적으로 고유한 유효 범위를 가지기 때문인데,
이것은 뷰 프레임워크 내부적으로 정의된 특징이다.
위의 cmp2Data의 결과에는 아무 값도 나타나지않는다.
이것은 컴포넌트의 유호범위로 인해 다른 컴포넌트의 값을
직접 접근하지 못한다는 결과이다.
그래서 뷰에서는 가장 기본적인 데이터 전달방법은 상 . 하위 컴포넌트 관계를 가지는 데이터 전달방법이다.
상위에서 하위로, 하위에서 상위로 보낼때는어떠한 방법을 사용할까???
<child-component v-bind:propsdata="message"></child-component>
//하위 컴포넌트
Vue.component('child-component',{
props:['propsdata'],
});
//상위 컴포넌트
new Vue({
el: '#app',
data:{
message: 'Hello Vue!'
}
})
하위 컴포넌트에서 -> v-bind:props 속성이름="상위컴포넌트data속성"
//$emit()으로 이벤트 발생
this.$emit('이벤트명');
//이벤트 수신
v-on:이벤트명="상위 컴포넌트 메서드명"
<child-component v-on:show-log="printText"></child-component>
<script>
Vue.component('child-component',{
template: '<button v-on:click="showLog">show</button>,
methods: {
showLog: function(){
this.$emit('show-log');
//하위에서 이벤트 발생
}
}
});
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
},
methods:{
printText: function(){
console.log("received an event");
}
}
});
</scrpit>
// 대부분 사용 되는
var eventBus = new Vue();
//이벤트 보내는 컴포넌트
methods: {
메서드명: function(){
eventBus.$emit('이벤트명', 데이터);
}
}
//이벤트 받는 컴포넌트
methods: {
created: function(){
eventBus.$on('이벤트명', function(데이터){
});
}
}
라우팅? : 웹페이지 간의 이동 방법을 이야기한다.
뷰 커뮤니티에서 가장 많이 사용되는 HTTP 통신 라이브러리이다. 엑시오스는 Promise 기반의 API 형식이 다양하게 제공되어 간편한 API만으로 로직을 구현하기 쉽다
//HTTP GET
axios.get('URL 주소').then().catch();
//HTTP POST 요청
axios.post('URL 주소').then().catch();
Do it Vue.js 입문(장기효 지음) 책에서 정리한 내용입니다.