Vue中组件生命周期过程详解
一、什么是生命周期?Vue中的生命周期是指:组件从创建到销毁的一个过程,在这过程中,我们在每个特定阶段会触发一些方法(这些方法具备一些功能),我们给这些方法起了名字叫做(生命周期钩子函数/组件钩子)二、为什么要学习生命周期我们需要在生命周期钩子中实现项目功能,那么我们必须要知道每一个钩子函数的具体用途。三、生命周期指的是组件的生命周期。Vue的生命周期分为三个阶段,分别为:初始化,运行中...
一、什么是生命周期?
Vue中的生命周期是指:组件从创建到销毁的一个过程,在这过程中,我们在每个特定阶段会触发一些方法(这些方法具备一些功能),我们给这些方法起了名字叫做(生命周期钩子函数/组件钩子)
二、为什么要学习生命周期
我们需要在生命周期钩子中实现项目功能,那么我们必须要知道每一个钩子函数的具体用途。
三、生命周期指的是组件的生命周期。
Vue的生命周期分为三个阶段,分别为:初始化,运行中,销毁,一共8个钩子;
生命周期钩子函数不允许写成箭头函数
- 所有的生命周期钩子自动绑定 this 上下文到实例中,因此你可以访问数据,对属性和方法进行运算。如果使用箭头函数来定义一个生命周期方法 (例如 created: () => this.fetchTodos()),箭头函数this绑定了父上下文,因此 this 与你期待的 Vue 实例不同,this.fetchTodos 的行为未定义。
四、生命周期分阶段详解
Vue官网对生命周期的详细示意图
整个生命周期所有钩子函数如下:
<body>
<div id="app">
<Test></Test>
</div>
<template id="test">
<div>
<h3>这是Test组件</h3>
<p> {{ msg }} </p>
</div>
</template>
</body>
<script>
new Vue({
el:'#app',
components:{
'Test':{
template:"#test",
data(){
return {
msg:'Hello 你好'
}
},
beforeCreate(){
console.log('1-beforeCreate');
console.log('data',this.msg);
console.log('真实的dom:',document.querySelector('p'));
// fetch('./data.json')
// .then(res => res.json())
// .then(data => this.msg = data)
// .catch(error=>console.log(error))
},
created(){
console.log('2-created');
console.log("data",this.msg);
console.log('真实的dom:',document.querySelector('p'));
// fetch('./data.json')
// .then(res=>res.json())
// .then(data=>this.msg=data)
// .catch(error=>console.log(error))
},
beforeMount () {
console.log('3-beforeMount');
console.log('data',this.msg);
console.log('真实的dom',document.querySelector('p'));
// fetch('./data.json')
// .then(res => res.json())
// .then(data => this.msg=data)
// .catch(error => console.log(error))
},
mounted () {
console.log('4-mounted');
console.log('data',this.msg);
console.log('真实的dom',document.querySelector('p'));
fetch('./data.json')
.then(res => res.json())
.then(data => this.msg = data)
.catch(error => console.log(error))
},
// ----------------------- 运行中-----------------------
beforeUpdate () {
console.log('beforeUpdate');
//通过页面数据查看是否渲染 console.log('data',$refs.msg.innerHTML);
console.log('真实的dom',document.querySelector('p'))
},
updated () {
console.log('update');
//通过页面数据查看是否渲染 console.log('data',$refs.msg.innerHTML);
console.log('真实的dom',document.querySelector('p'))
}
// ----------------------- 销毁阶段-----------------------
/*
beforeDestroy () {
console.log('beforeDestroy')
},
destroyed () {
console.log('destroyed')
}
*/
}
}
})
</script>
初始化阶段
** 初始化阶段的4个钩子: beforeCreate、created、beforeMount、mounted;**
beforeCreate:阶段
beforeCreate () {
console.log('1-beforeCreate');
console.log('data',this.msg);//undefined
console.log('真实的dom:',document.querySelector('p'));//null
fetch('./data.json')
.then(res => res.json())
.then(data => this.msg = data)
.catch(error => console.log(error))
}
- 1、组件创建前触发,目的是为组件的 生命周期和组件中的事件做准备;
- 2、没有获得数据,真实dom也没有渲染出来
- 3、在此阶段内可以进行数据请求,提供一次修改数据的机会
- 4、此阶段执行一次
created:阶段
created () {
console.log('2-created');
console.log("data",this.msg);
console.log('真实的dom:',document.querySelector('p'));
fetch('./data.json')
.then(res => res.json())
.then(data => this.msg = data)
.catch(erro r=> console.log(error))
}
- 1、组件创建结束
- 2、数据可以拿到了
- 3、可以进行数据请求,提供一次修改数据的机会
- 4、该过程执行一次
beforeMount:阶段
beforeMount () {
console.log('3-beforeMount');
console.log('data',this.msg);
console.log('真实的dom',document.querySelector('p'));
fetch('./data.json')
.then(res => res.json())
.then(data => this.msg=data)
.catch(error => console.log(error))
},
- 1、组件挂载前
- 2、该阶段任务:
- 判断el,判断template;
- 如果el没有,那么我们需要手动挂载,如果有,那麽判断template;
- 如果template有,那么进行render函数,如果template没有,那么通过outHTML手动书写模板;
- 3、数据可以获得,但是真实dom还没有渲染
- 4、可以进行数据请求,也提供了一次数据修改的机会
mounted:阶段
mounted () {
console.log('4-mounted');
console.log('data',this.msg);
console.log('真实的dom',document.querySelector('p'));
fetch('./data.json')
.then(res => res.json())
.then(data => this.msg = data)
.catch(error => console.log(error))
}
- 1、组件挂载结束
- 2、数据获得,真实dom也获得了
- 3、可以进行数据请求,也可以修改数据
- 4、执行一次
- 5、可以进行真实dom的操作了
总结:数据请求我们一般写在created钩子中,第三方库的实例化我们一般写在mounted钩子中;
运行中阶段
运行中阶段有两个钩子:beforeUpdate、updated;
运行中阶段触发条件是:数据更新
beforeUpdate:阶段
数据更新前阶段
beforeUpdate () {
console.log('beforeUpdate');
//重新渲染 VDOM , 然后通过diff算法比较两次vdom,生成patch 补丁对象
console.log('=即将更新渲染=');
console.log('页面data',this.$refs.msg.innerHTML);
console.log('真实的dom',document.querySelector('p'))
},
-
- 更新前
-
- 重新渲染 VDOM , 然后通过diff算法比较两次vdom,生成patch 补丁对象,还未渲染到页面
-
- 这个钩子函数更多的是内部进行一些操作
-
- 可以触发多次,只要数据更新就会触发
updated () {
console.log('update');
console.log('==更新成功==');
console.log('data',this.$refs.msg.innerHTML);
console.log('真实的dom',document.querySelector('p'))
}
-
- 数据更新结束
-
- 真实dom得到了,数据也得到了( 更新后的 )
-
- 可以用于动态数据获取( 第三方库实例化 )
-
- 可以触发多次,只要数据更新就会触发
- 可以触发多次,只要数据更新就会触发
销毁阶段
销毁阶段也是有两个钩子:beforeDestroy、destroyed.这两个钩子用法基本相同。
这两个钩子用法:计时器的关闭 第三方实例的删除
组件销毁需要触发条件:
- 1、可以通过组件外部定义开关控制组件的销毁
- 2、组件内部定义$destroy()的方法,通过调用该方法控制组件销毁。
例子1:通过组件外部定义开关销毁组件
<body>
<div id="app">
<Test v-if="flag"></Test>
<button @click="flag=!flag">销毁</button>
</div>
<template id="test">
<div>
<h3>这是Test组件</h3>
<p ref="msg"> {{ msg }} </p>
</div>
</template>
</body>
new Vue({
el:"#app",
data:{
flag:true,
},
components:{
'Test':{
template:'#test',
data(){
return {
msg:'Hello 你好'
}
},
beforeDestroy () {
console.log('beforeDestroy')
},
destroyed () {
console.log('destroyed')
}
}
}
})
例子2:组件内部调用$destroy方法销毁组件
<body>
<div id="app">
<Test v-if="flag"></Test>
</div>
<template id="test">
<div>
<h3>这是Test组件</h3>
<p ref="msg"> {{ msg }} </p>
<button @click = "clear">销毁</button>
</div>
</template>
</body>
new Vue({
el:"#app",
components:{
'Test':{
template:'#test',
data(){
return {
msg:'Hello 你好'
}
},
methods:{
//内部通过$destroy方法删除自身组件,触发destroy生命钩子函数
clear() {
this.$destroy();
}
},
beforeDestroy () {
console.log('beforeDestroy');
//组件已经销毁,但是渲染出的真实dom结构未被销毁,手动销毁
document.querySelector('#app').remove()
},
destroyed () {
console.log('destroyed')
}
}
}
})
对比: 内部销毁 vs 外部销毁
- 外部销毁不仅能销毁组件,也能销毁该组件的dom结构
- 内部销毁只能销毁组件,不能销毁组件的dom结构,dom结构需要手动销毁
以上仅为个人观点
更多推荐
所有评论(0)