【Vue】Vue扫盲(一)事件标签、事件修饰符:@click.prevent @click.stop @click.stop.prevent、按键修饰符、及常用指令
【Vue】Vue扫盲(二)指令:v-for 、v-if、v-else-if、v-else、v-show
【Vue】Vue扫盲(三)计算属性和监听器
【Vue】Vue扫盲(四)组件化思想与简单应用
文章目录
- 一、Vue 生命周期概述
- 1.Vue 生命周期概述
- 2.主要的生命周期钩子函数
- 二、主要的生命周期钩子函数
- beforeCreate
- created
- beforeMount
- mounted
- beforeUpdate
- updated
- beforeDestroy
- destroyed
- 三、执行时机验证:
- 四、实际应用场景
- 一、数据获取与初始化
- 1.从服务器获取数据
- 2.初始化组件数据
- 二、DOM 操作相关
- 1.操作挂载后的 DOM 元素
- 2.第三方插件或库的初始化
- 三、响应数据变化与性能优化
- 1.数据更新时的额外操作
- 2.处理复杂的计算属性更新
- 四、资源清理与内存管理
- 1.定时器与事件监听器的清除
- 2.取消异步操作
- 五、总结
在 Vue.js 开发中,理解生命周期和钩子函数是非常重要的。它们允许我们在不同阶段对组件进行特定的操作,从而实现更加灵活和强大的应用。
每个 Vue 实例在被创建时都要经过一系列的初始化过程 : 创建实例, 装载模板, 渲染模
板等等。 Vue 为生命周期中的每个状态都设置了钩子函数(监听函数) 。 每当 Vue 实例处于
不同的生命周期时, 对应的函数就会被触发调用
一、Vue 生命周期概述
Vue 实例在创建和运行过程中会经历一系列的阶段,每个阶段都有相应的钩子函数可以让我们在特定时刻执行自定义的逻辑。Vue 的生命周期大致可以分为以下几个阶段:
1.Vue 生命周期概述
- 创建阶段:在这个阶段,Vue 实例被初始化,包括数据观测、事件绑定等操作。
- 挂载阶段:Vue 实例被挂载到 DOM 上,此时可以访问到 DOM 元素。
- 更新阶段:当数据发生变化时,Vue 会重新渲染组件,触发更新阶段的钩子函数。
- 销毁阶段:当组件被销毁时,会执行一些清理操作,如解绑事件、移除 DOM 元素等。
2.主要的生命周期钩子函数
主要的生命周期钩子函数
- beforeCreate
- created
- beforeMount
- mounted
- beforeUpdate
- updated
- beforeDestroy
- destroyed
真正的执行顺序:在 Vue 实例的生命周期中,钩子函数执行的顺序
创建阶段
- beforeCreate:首先执行这个钩子函数。此时,Vue 实例刚刚被初始化,数据观测(data observer)和事件机制还未被设置,无法访问到data、computed、methods等实例属性。
- created:在beforeCreate之后执行。实例已经完成了数据观测、属性和方法的运算,初始化事件,此时可以访问data中的数据,也可以调用methods中的方法,但此时还未开始挂载到
DOM。
挂载阶段
- beforeMount:在创建完成之后、挂载开始之前被调用。此时,模板已经编译好了,但还没有挂载到真实的 DOM 上,el属性还未被替换成真实的 DOM 元素。
- mounted:在beforeMount之后执行。实例已经挂载到真实的 DOM 上,可以通过this.$el访问到挂载后的 DOM 元素。通常在这个钩子函数中进行一些 DOM 操作,如获取 DOM 元素的高度、宽度等。
更新阶段(当数据发生变化时触发)
- beforeUpdate:数据更新时,在虚拟 DOM 重新渲染和打补丁之前被调用。可以在这个钩子中进一步地更改状态,但不会触发额外的重新渲染循环。
- updated:在虚拟 DOM 重新渲染和打补丁之后被调用。此时,DOM 已经根据数据的变化更新完毕,可以执行依赖于更新后的 DOM 的操作。
销毁阶段
- beforeDestroy:在实例销毁之前被调用。此时实例仍然完全可用,可以在这个钩子函数中进行一些清理工作,如清除定时器、解绑自定义事件监听器等。
- destroyed:在beforeDestroy之后执行。此时,Vue 实例的所有绑定(如指令绑定、事件监听器等)都已经被解除,子实例也被销毁,实例相关的所有东西都被拆除。
二、主要的生命周期钩子函数
beforeCreate
beforeCreate:在实例初始化之后,数据观测和事件配置之前被调用。此时,实例的选项对象还没有被解析,无法访问data、computed、watch等属性。
new Vue({
beforeCreate() {
console.log('beforeCreate');
},
data() {
return {
message: 'Hello Vue!'
};
}
});
created
created:在实例创建完成后被立即调用。此时,实例已经完成了数据观测、事件配置和方法的初始化,可以访问data、computed、watch等属性,但 DOM 还未被挂载。
new Vue({
created() {
console.log('created');
console.log(this.message); // 可以访问到 data 中的属性
},
data() {
return {
message: 'Hello Vue!'
};
}
});
beforeMount
beforeMount:在挂载开始之前被调用。此时,模板已经编译完成,但还未被渲染到 DOM 中。
new Vue({
beforeMount() {
console.log('beforeMount');
},
template: '<div>{{ message }}</div>',
data() {
return {
message: 'Hello Vue!'
};
}
});
mounted
mounted:在挂载完成后被调用。此时,实例已经被挂载到 DOM 上,可以访问到 DOM 元素。
new Vue({
mounted() {
console.log('mounted');
const div = document.querySelector('div');
console.log(div.textContent); // 输出 'Hello Vue!'
},
template: '<div>{{ message }}</div>',
data() {
return {
message: 'Hello Vue!'
};
}
});
beforeUpdate
beforeUpdate:在数据更新时,但在虚拟 DOM 重新渲染和打补丁之前被调用。可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。
new Vue({
data() {
return {
count: 0
};
},
beforeUpdate() {
console.log('beforeUpdate');
},
template: '<div>{{ count }}</div>',
methods: {
increment() {
this.count++;
}
}
});
updated
updated:在数据更新之后,虚拟 DOM 重新渲染和打补丁之后被调用。此时,组件的 DOM 已经更新,可以执行依赖于 DOM 的操作。
new Vue({
data() {
return {
count: 0
};
},
updated() {
console.log('updated');
},
template: '<div>{{ count }}</div>',
methods: {
increment() {
this.count++;
}
}
});
beforeDestroy
beforeDestroy:在实例销毁之前被调用。在这个阶段,实例仍然完全可用,可以执行一些清理操作,如解绑事件、清除定时器等。
new Vue({
beforeDestroy() {
console.log('beforeDestroy');
// 清除定时器
clearInterval(this.timer);
},
data() {
return {
message: 'Hello Vue!'
};
},
created() {
// 设置定时器
this.timer = setInterval(() => {
console.log('Timer is running.');
}, 1000);
}
});
destroyed
destroyed:在实例销毁之后被调用。此时,实例的所有绑定和事件监听器都已被移除,子实例也都被销毁。
new Vue({
destroyed() {
console.log('destroyed');
},
data() {
return {
message: 'Hello Vue!'
};
},
created() {
// 设置定时器
this.timer = setInterval(() => {
console.log('Timer is running.');
}, 1000);
},
beforeDestroy() {
clearInterval(this.timer);
}
});
三、执行时机验证:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>单项绑定 v-bind</title>
</head>
<body>
<div id ="app">
<span id="num">{{num}}</span>
<button @click="num++">赞</button>
<h3>{{name}},有{{num}}点赞</h3>
</div>
<script src="../node_modules/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el:"#app",
data:{
name:"张三",
num:100
},
methods: {
show(){
return this.name;
},
add(){
this.num++;
}
},
beforeCreate() {
console.log("==============beforeCreate===============");
console.log("数据模型未加载:"+this.name,this.num);
console.log("html模版已加载:"+document.getElementById("num").innerText);
console.log("方法未加载:"+this.show());
},
created() {
console.log("==============created===============");
console.log("数据模型已加载:"+this.name,this.num);
console.log("方法已加载:"+this.show());
console.log("html模版已经加载:"+document.getElementById("num"));
console.log("html模版未渲染:"+document.getElementById("num").innerText);
},
beforeMount() {
console.log("==============beforeMount===============");
console.log("html模版未渲染:"+document.getElementById("num").innerText);
},
mounted() {
console.log("==============mounted===============");
console.log("html模版已渲染:"+document.getElementById("num").innerText);
},
beforeUpdate() {
console.log("==============beforeUpdate===============");
console.log("数据模型已更新:"+this.name,this.num);
console.log("html模版未更新:"+document.getElementById("num").innerText);
},
updated() {
console.log("==============updated===============");
console.log("数据模型已更新:"+this.name,this.num);
console.log("html模版已更新:"+document.getElementById("num").innerText);
},
})
</script>
</body>
</html>
效果1:进入页面的时候 执行情况如下
效果2:点击更新后, 执行情况如下
四、实际应用场景
一、数据获取与初始化
1.从服务器获取数据
在created钩子函数中,由于实例已经完成了数据观测、事件配置和方法的初始化,可以发起异步请求来获取服务器端的数据。例如,从 API 获取用户信息并填充到组件的data属性中。
new Vue({
created() {
axios.get('/api/userInfo').then(response => {
this.user = response.data;
});
},
data() {
return {
user: null
};
}
});
2.初始化组件数据
对于一些本地数据的初始化,如设置默认值或者根据初始条件计算某些数据,也可以在created钩子中进行。例如,根据用户权限初始化菜单列表。
new Vue({
created() {
if (this.user.role === 'admin') {
this.menuList = ['dashboard', 'users', 'settings'];
} else {
this.menuList = ['dashboard'];
}
},
data() {
return {
user: {role: 'user'},
menuList: []
};
}
});
二、DOM 操作相关
1.操作挂载后的 DOM 元素
在mounted钩子函数中,因为实例已经挂载到 DOM 上,可以安全地进行 DOM 操作。比如获取某个 DOM 元素的尺寸、添加自定义的 DOM 事件监听器等。
new Vue({
mounted() {
const element = document.querySelector('.my - element');
console.log(element.offsetWidth);
element.addEventListener('click', this.handleClick);
},
methods: {
handleClick() {
console.log('Element clicked!');
}
}
});
2.第三方插件或库的初始化
许多第三方插件需要在 DOM 元素存在后进行初始化。例如,初始化一个自定义的日期选择器插件,需要在mounted钩子中进行操作。
new Vue({
mounted() {
const picker = new DatePicker('#date - picker - element');
}
});
三、响应数据变化与性能优化
1.数据更新时的额外操作
在beforeUpdate和updated钩子函数中,可以在数据更新时进行额外的操作。例如,在beforeUpdate中判断数据是否真正发生变化,如果没有实质变化则阻止不必要的 DOM 更新,从而提高性能。
new Vue({
data() {
return {
value: 0
};
},
beforeUpdate() {
if (this.oldValue === this.value) {
// 阻止更新
return;
}
this.oldValue = this.value;
},
updated() {
// 执行依赖于更新后DOM的操作
}
});
2.处理复杂的计算属性更新
当计算属性依赖于多个数据并且更新逻辑复杂时,可以在beforeUpdate或updated钩子中进行相关的逻辑处理,确保计算属性的结果正确更新并且不会造成性能问题。
四、资源清理与内存管理
1.定时器与事件监听器的清除
在beforeDestroy钩子函数中,当组件被销毁时,可以清除定时器、解绑事件监听器等,以避免内存泄漏。例如,如果在组件创建时设置了一个定时器,在beforeDestroy中就需要将其清除。
new Vue({
data() {
return {
timer: null
};
},
created() {
this.timer = setInterval(() => {
console.log('Timer running');
}, 1000);
},
beforeDestroy() {
clearInterval(this.timer);
}
});
2.取消异步操作
如果组件中有正在进行的异步操作(如未完成的网络请求),在beforeDestroy中可以尝试取消这些操作,以防止不必要的资源消耗或者数据不一致性。例如,使用axios的取消请求功能。
new Vue({
data() {
return {
cancelToken: null,
data: null
};
},
created() {
const source = axios.CancelToken.source();
this.cancelToken = source.token;
axios.get('/api/data', {cancelToken: source.token}).then(response => {
this.data = response.data;
});
},
beforeDestroy() {
if (this.cancelToken) {
axios.cancel(this.cancelToken);
}
}
});
五、总结
Vue 的生命周期和钩子函数为我们提供了强大的工具,使我们能够在不同阶段对组件进行精细的控制。通过合理地使用这些钩子函数,我们可以实现更加高效、灵活和可维护的 Vue 应用程序。在实际开发中,我们应该根据具体的需求选择合适的钩子函数来执行相应的操作,以提高开发效率和应用性能。