一、生命周期 & 生命周期函数
1. 生命周期(Life Cycle)是指一个组件从创建 -> 运行 -> 销毁的整个阶段,强调的是一个时间段。
2. 生命周期函数:是由 vue 框架提供的内置函数,会伴随着组件的生命周期,自动按次序执行,不需要用户显式地调用。 —— 钩子函数
注意: 生命周期强调的是时间段,生命周期函数强调的是时间点。
二、组件生命周期函数的分类
三、生命周期图示
四、Vue2.0的生命周期函数
组件的生命周期经历的阶段:
1. 创建阶段:beforeCreate、created、beforeMount、mounted
2. 运行阶段:beforeUpdate、updated
3. 销毁阶段:beforeDestroy、destroyed
1. 创建阶段
(1)beforeCreate
创建阶段的第1个生命周期函数,组件的props,methods,data尚未被创建,处于不可用。
在组件创建之前运行,此时Vue实例的el、data、data中的变量均为undefined
(2)created(最早可以发起Ajax请求)
创建阶段的第2个生命周期函数,组件的props,methods,data已创建好,可以使用,但组件的模板结构尚未生成 ,不能操作DOM,但最早可以发起Ajax请求
组件已经创建完成,data、props已经初始化了,el还是undefined(组件还没有挂载到DOM上)
经常通过created函数调用methods中的方法,请求服务器的数据,并且把请求到的数据转存到data中,供template模板渲染时去使用
(3)beforeMount
创建阶段的第3个生命周期函数,内存编译好的HTML结构准备渲染到浏览器中,此时浏览器中还没有当前组件的DOM结构,无法操作DOM
el被绑定(和DOM绑定),但未挂载
(4)mounted(最早可以操作DOM)
创建阶段的第4个生命周期函数,已经渲染内存的HTML结构到浏览器中,包含了当前组件的DOM结构,最早可以操作DOM
组件挂载之后,el绑定、组件挂载
2. 运行阶段(根据数据变化进入运行阶段)
(1) beforeUpdate
运行阶段的第1个生命周期函数,将要根据数据变化后、最新的数据,重新渲染组件的模板结构,此时数据变化后还未放到模板结构上
当组件的内容被改变、隐藏的组件被显示、显示的组件被隐藏等触发
(2)updated(当数据变化后,为了能够操作到最新的DOM结构)
运行阶段的第2个生命周期函数,完成了最新数据重新渲染到组件的DOM结构
当数据变化后,为了能够操作到最新的DOM结构,应将代码写在update中
更新结束后触发
3. 销毁阶段
(1)beforeDestroy
销毁阶段的第1个生命周期函数,组件还处于正常工作状态。
在组件销毁之前。组件还是正常使用
(2) destroyed
Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
组件销毁之后
4. keep-alive组件:是vue的内置组件,用来保持vue组件运行的某种状态,避免被重新渲染
第一步:创建组件(定义组件),组件文件的扩展名(后缀)可以是.vue,也可以是.js
第二步:在使用组件的位置导入,注册组件
第三步:使用组件:像html标签一样使用
五、示例
我们创建了一个Vue根实例命名为app,将其挂载到页面id为app的dom元素上。
局部注册的一个组件child并在根实例中将其注册使其可以在根实例的作用域中使用。
将子组件用<keep-alive> 包裹,为接下来的测试作准备。
keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。
在vue项目中,难免会有列表页面或者搜索结果列表页面,点击某个结果之后,返回回来时,如果不对结果页面进行缓存,那么返回列表页面的时候会回到初始状态,但是我们想要的结果是返回时这个页面还是之前搜索的结果列表,这时候就需要用到vue的keep-alive技术了。”
<script src="./js/vue.js"></script>
<body>
<div id="app">
<p>{{ message }}</p>
<keep-alive>
<my-components msg="hello" v-if="show"></my-components><!-- 子组件 -->
</keep-alive>
</div>
<script>
//1.定义子组件
var child = {
template:'<div>from child: {{msg}}</div>',//子组件的html模板内容
props:['msg'],//接收父组件传递的msg
data:function(){
return {
childMsg:'child'
}
},
deactivated:function(){//钩子函数:在组件非运行时触发
console.log('component deactivated!');
},
activated:function(){//钩子函数:在组件运行时触发
console.log('component activated!');
}
}
//2.创建Vue实例:和DOM中的id为app的元素绑定
const vm = new Vue({
el:'#app',
components:{//注册子组件
'my-components':child
},
data(){
return {
message:'father',
show:true
}
},
// 3.定义生命周期函数
beforeCreate:function(){
console.group('beforeCreate 组件创建之前的状态---------------')
let state = {
'el':this.$el,
'data':this.$data,
'message':this.message
}
console.log(state);
},
created:function(){
console.group('created 组件创建完成的状态---------------');
let state = {
'el':this.$el,
'data':this.$data,
'message':this.message
}
console.log(state);
},
beforeMount:function(){
console.group('beforeMount 组件挂载前的状态---------------');
let state = {
'el':this.$el,
'data':this.$data,
'message':this.message
}
console.log(this.$el);
console.log(state);
},
mounted:function(){
console.group('mounted 组件挂载结束的状态---------------');
let state = {
'el':this.$el,
'data':this.$data,
'message':this.message
}
console.log(this.$el);
console.log(state);
},
beforeUpdate:function(){
console.group('beforeUpdate 更新前的状态---------------');
let state = {
'el':this.$el,
'data':this.$data,
'message':this.message
}
console.log(this.$el);
console.log(state);
console.log('beforeUpdate == '+document.getElementsByTagName('p')[0].innerHTML);
},
updated:function(){
console.group('updated 更新完成的状态---------------');
let state = {
'el':this.$el,
'data':this.$data,
'message':this.message
}
console.log(this.$el);
console.log(state);
console.log('updated == '+document.getElementsByTagName('p')[0].innerHTML);
},
beforeDestroy:function(){
console.group('beforeDestroy 组件销毁前的状态---------------');
let state = {
'el':this.$el,
'data':this.$data,
'message':this.message
}
console.log(this.$el);
console.log(state);
},
destroyed:function(){
console.group('destroyed 组件销毁完成的状态---------------');
let state = {
'el':this.$el,
'data':this.$data,
'message':this.message
}
console.log(this.$el);
console.log(state);
}
})
</script>
</body>
beforecreate:el 和 data 并未初始化 ;
created:完成了 data 数据的初始化,el没有;
beforeMount:完成了 el 和 data 初始化 ;
mounted :完成挂载。(注意:在beforeMount阶段应用的 Virtual DOM(虚拟Dom)技术,先把坑占住了,到后面mounted挂载的时候再把值渲染进去。)
2. activated 和 destroyed相关
我们发现了activated周期钩子已经被触发,这是因为子组件my-components被<keep-alive> 包裹,随el的挂载触发。
现在我们将此组件停用进行测试:由于子组件具有一个v-if指令v-if=”show”,因此我们可以通过将show的值置为false将其销毁。控制台输入 对象名.show = false;测试结果如下:
由于在这里我们修改了data的值,所以会触发beforeUpdate和updated钩子,这里先不讨论这一组钩子,我们看到deactivated钩子已经触发,表示<keep-alive>已经停用,符合预期结果。
现在我们对Vue实例进行销毁,调用app.$destroy()方法即可将其销毁,控制台测试如下:
这里我们将data中的message属性改成了’message’,发现dom并没有进行相应的响应,这证实了之前的说法。同样,如果你在子组件也加入destroyed钩子,发现该钩子也会被触发,这也证明了子实例也会被一起销毁。这里的销毁并不指代’抹去’,而是表示’解绑’。
3. updated相关
beforeUpdate和updated是最后一对周期钩子了。
我们发现beforeUpdate和updated触发时,el中的数据都已经渲染完成,但根据beforeUpdate == father而updated == message可知,只有updated钩子被调用时候,组件dom才被更新。
在beforeUpdate可以监听到data的变化,但是view层没有被重新渲染,view层的数据没有变化。等到updated的时候,view层才被重新渲染,数据更新。
六、使用建议
1. 在created钩子中可以对data数据进行操作,这个时候可以进行ajax请求将返回的数据赋给data
2. 在mounted钩子对挂载的dom进行操作
3. 在使用vue-router时有时需要使用<keep-alive></keep-alive>来缓存组件状态,这个时候created钩子就不会被重复调用了,如果我们的子组件需要在每次加载的时候进行某些操作,可以使用activated钩子触发。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/79742.html