vue2的生命周期

作者 likaiqiang 日期 2017-03-20
vue2的生命周期

生命周期就是一个vue实例从诞生到死亡的过程,下图中红线框中表示一个vue实例的钩子函数

vue生命周期的钩子函数:

  1. beforeCreate
  2. created
  3. beforeMount
  4. mounted
  5. beforeUpdate
  6. updated
  7. beforeDestroy
  8. destoryed

整个vue的生命周期就好比一个人成长的过程,他的钩子函数就表示在他人生的不同阶段做不同的事。

  1. 出生前(各种器官发育不全)
  2. 呱呱落地了
  3. 未成年
  4. 满18岁了(进入社会了,开始与万恶的dom做斗争了)
  5. 开始积累社会经验了
  6. 每次积累经验都会触发update
  7. 临死前
  8. game over

开个脑洞,进入正题

beforeCreate——>created

举个例子:

var app = new Vue(){
el:'#app',
data(){
return {
text:'vue'
}
},
methods:{
getInfo(){
return 'vuex'
}
}
}

然后试图在他的生命周期的不同钩子函数内访问text变量与getInfo()方法。

var app = new Vue({
el:'#app',
data(){
return {
text:'vue'
}
},
methods:{
getInfo(){
return 'vuex'
}
},
beforeCreate(){
console.log('beforeCreate');
console.log(this.text,this.getInfo())
},
created(){
console.log('created',this.text,this.getInfo());
},
beforeMount(){
console.log('beforeMount',this.text,this.getInfo())
},
mounted(){
console.log('mounted',this.text,this.getInfo())
},
beforreUpdate(){
console.log('beforreUpdate',this.text,this.getInfo())
},
updated(){
console.log('updated',this.text,this.getInfo())
},
beforeDestory(){
console.log('beforeDestory',this.text,this.getInfo())
},
destoryed(){
console.log('destoryed',this.text,this.getInfo())
}
})

chrome控制台:

有一个错误,getInfo不是一个函数,说明在beforeCreate阶段,不能访问vue实例上面的属性或者方法。

而后面的created、beforeMount、mounted阶段均可以输出vue与vuex,由此证明这三个钩子函数均可以访问vue实例的属性和方法。

其实除了beforeCreated,其他阶段均可以访问vue实例的属性和方法,只不过后面那几个在这里没有表现出来罢了。

可以想象一下,把beforeCreate——>created看成一个vue实例从无到有的过程,但是这时它还没有渲染到dom上,只是一个存在于内存中的vue对象.

created——>mounted

这个阶段把vue对象渲染到dom,换个例子:

<div id="app">
<ul>
<li v-for="(item,index) in arr" :key='index'>{{item}}</li>
</ul>
</div>
var app = new Vue({
el:'#app',
data(){
return {
arr:[1,2,3]
}
},
methods:{
logLi(){
var lis = document.querySelectorAll('li');
console.log(lis.length);
}
},
created(){
console.log('created');
this.logLi();
},
beforeMount(){
console.log('beforeMount');
this.logLi();
},
mounted(){
console.log('mounted');
this.logLi();
}
})

chrome控制台:

可以看到只有mounted函数内才输出了正确的结果,由此证明,mounted函数被调起时vue已经完成了dom的渲染。至此,一个vue实例真真正正从无到有完成。

beforeUpdate——>updated

这个过程是响应vue实例数据的变化时被调用的,一个vue实例上任一数据变化都会调用这个钩子。

使用这个函数要注意一点,只有某个数据被渲染到了dom上,这个数据的变化才会触发update函数。

举个例子:

<div id="app">
<p>{{text1}}</p>
<p></p>
</div>
var app = new Vue({
el:'#app',
data(){
return {
text1:123,
text2:456
}
},
updated(){
console.log('updated');
}
})

在chrome控制台分别改变text1与text2的值

app.text1++ //123 upadted
app.text2++ //456

updated函数只响应text1的变化,由此可见beforeUpdate与updated函数只响应已经渲染到dom上数据的变化。

PS:updated会响应所有的数据变化,如果要在处理某一个数据的变化响应呢?可以用watch。

var app = new Vue({
el:'#app',
data(){
return {
text1:123,
text2:456
}
},
updated(){
console.log('updated');
},
watch:{
'text1':function(){
console.log('text1 update');
},
'text2':function(){
console.log('text2 update');
}
}
})

Vue.js 默认异步更新 DOM。每当观察到数据变化时,Vue就开始一个队列,将同一事件循环内所有的数据变化缓存起来。如果一个watcher被多次触发,只会推入一次到队列中。等到下一次事件循环,Vue 将清空队列,只进行必要的 DOM 更新。

什么意思呢?举个例子:

var app = new Vue({
el:'#app',
data(){
return {
text:null
}
},
mounted(){
this.text = 1;
this.text = 2;
this.text = 3;
this.text = 4;
},
updated(){
console.log('updated');
console.log(this.text);
}
})

事实上chrome控制台只会输出 updated 4,这样做是为了减少dom操作次数,提高性能。如果要在下一个‘tick’更新后做点什么,按照以前的方法就会有点棘手,vue为我们提供了一个新的api nextTick()来解决这个问题。

mounted(){
this.text = 1;
this.text = 2;
this.text = 3;
this.text = 4;
this.$nextTick(()=>{
this.text = 100;
})
}

最后说一下destroy,这个函数用于销毁一个vue实例,不会主动触发,例如页面上的弹出层,弹出层关闭后应该销毁掉这个弹出层实例。

伪代码:

dialog.close(()=>{
vm.destroyed();
})

被销毁后的vue实例数据与方法还在,但是不再响应数据的变化,活脱脱的死尸一个。