文章目录
一. Vue3与Vue2的区别
1. Vue3与Vue2的响应式(重要
)
(1) vue2的响应式
Vue2的响应式原理主要是基于Object.defineProperty()方法实现的。在Vue2的数据劫持过程中,会对数据对象的所有属性进行监听,当数据发生改变时,依赖于该属性的视图会自动更新。
具体流程:
通过Object.defineProperty()方法,对数据对象进行劫持,为每个数据对象的属性都创建一个Dep对象。
当属性被读取时,会触发getter()方法,将视图添加到该属性的Dep对象中。
当属性被修改时,会触发setter()方法,通知Dep对象中所有的视图进行更新。
在视图更新时,Vue2采用的是异步渲染的方式,即将所有需要更新的视图都添加到一个队列中,然后在下一个事件循环中执行更新操作,这种方式可以避免频繁的更新操作导致的性能问题。同时,Vue2还对常用的数据类型(如数组、对象)进行了深度监听,并且提供了一些常用的修饰符(如.sync、.lazy等)来方便开发者进行数据的双向绑定和表单的操作。
核心理解:
对于对象来说: 通过defineProperty对对象的已有属性值的读取和修改进行劫持(监视/拦截)
对于数组来说:通过重写数组更新数组一系列更新元素的方法来实现元素修改的劫持
Object.defineProperty(data, 'count', {
get () {}, // 通过get方法获取数据
set () {} // 通过set方法更新数据
})
使用这种方式会造成的问题:
- 对象直接新添加的属性或删除已有属性, 界面不会自动更新
- 直接通过下标替换元素或更新length, 界面不会自动更新 arr[1] = {}
(2) Vue3的响应式
具体流程:
Vue3 采用了 Proxy 作为数据劫持的底层实现,其中 Proxy 是 ES6 中新增的特性,可以用来代替 Object.defineProperty() 方法实现响应式。具体实现如下:
- 创建 reactive 对象
使用 reactive() 函数可以创建响应式对象,例如:
import { reactive } from 'vue';
const state = reactive({
count: 0,
});
- 访问响应式对象
访问响应式对象和普通对象一样,例如:
console.log(state.count); // 输出 0
- 修改响应式对象
修改响应式对象的值会触发视图更新,例如:
state.count = 1;
console.log(state.count); // 输出 1
- 嵌套响应式对象
Vue3 支持嵌套响应式对象,例如:
const state = reactive({
user: {
name: 'Tom',
age: 18,
},
});
- 添加/删除属性
添加/删除响应式对象的属性也会触发视图更新,例如:
state.user.gender = 'male'; // 添加属性
delete state.user.age; // 删除属性
通过以上方式,Vue3 实现了更加高效的响应式系统。
核心理解:
通过Proxy(代理): 拦截对data任意属性的任意(13种)操作, 包括属性值的读写, 属性的添加, 属性的删除等… 通过
Reflect(反射): 动态对被代理对象的相应属性进行特定的操作
new Proxy(data, {
// 拦截读取属性值
get (target, prop) {
return Reflect.get(target, prop)
},
// 拦截设置属性值或添加新属性
set (target, prop, value) {
return Reflect.set(target, prop, value)
},
// 拦截删除属性
deleteProperty (target, prop) {
return Reflect.deleteProperty(target, prop)
}
})
proxy.name = 'tom'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Proxy 与 Reflect</title>
</head>
<body>
<script>
const user = {
name: "John",
age: 12
};
/*
proxyUser是代理对象, user是被代理对象
后面所有的操作都是通过代理对象来操作被代理对象内部属性
*/
const proxyUser = new Proxy(user, {
get(target, prop) {
console.log('劫持get()', prop)
return Reflect.get(target, prop)
},
set(target, prop, val) {
console.log('劫持set()', prop, val)
return Reflect.set(target, prop, val); // (2)
},
deleteProperty (target, prop) {
console.log('劫持delete属性', prop)
return Reflect.deleteProperty(target, prop)
}
});
// 读取属性值
console.log(proxyUser===user)
console.log(proxyUser.name, proxyUser.age)
// 设置属性值
proxyUser.name = 'bob'
proxyUser.age = 13
console.log(user)
// 添加属性
proxyUser.sex = '男'
console.log(user)
// 删除属性
delete proxyUser.sex
console.log(user)
</script>
</body>
</html>
2. Vue3与Vue2的生命周期
(1) Vue2的生命周期
官方图例:
Vue2的生命周期包括以下几个阶段:
- beforeCreate:实例刚刚创建,数据观测和事件机制还未初始化。
- created:实例已经创建完成,数据观测和事件机制已经初始化完成,但是模板还未编译,$el属性还不存在。
- beforeMount:模板已经编译完成,但是还未将编译结果挂载到页面中。
- mounted:编译结果已经挂载到页面中,此时可以进行DOM操作。
- beforeUpdate:数据发生改变,但是还未更新到模板中。
- updated:数据已经更新到模板中,此时可以进行DOM操作。
- beforeDestroy:实例销毁前调用,此时实例还未销毁,可以进行善后工作,比如清除计时器。
- destroyed:实例已经销毁,此时所有的计时器和监听事件都已经被清除,不能再进行DOM操作。
- activated:组件被激活时调用,如在包含它的组件中使用v-if。
- deactivated:组件被取消激活时调用,如在包含它的组件中使用v-if。
需要注意的是,beforeCreate和created两个阶段是在实例被创建之后,但是模板还未进行编译之前,所以在这两个阶段中无法进行DOM操作。而mounted阶段之后,就可以进行DOM操作。
(2) Vue3的生命周期
官方图例:
Vue3的生命周期和Vue2有所不同,主要有以下生命周期:
- setup:这是Vue3中新增的生命周期,用于替代Vue2中的beforeCreate和created生命周期,用于配置组件,包括响应式数据、计算属性、方法等。
- beforeMount:组件即将挂载到页面的生命周期,用于处理异步操作。
- onMounted:组件挂载完成的生命周期,用于处理DOM操作和数据初始化。
- onUpdated:组件更新完成的生命周期,用于处理组件更新后的DOM操作和数据初始化。
- beforeUnmount:组件即将卸载的生命周期,用于清理资源和取消异步操作。
- onUnmounted:组件卸载完成的生命周期,用于清理资源和取消异步操作。
需要注意的是,Vue3中去掉了beforeDestroy和destroyed生命周期,取而代之的是beforeUnmount和onUnmounted。这是因为在Vue3中采用了基于Proxy对象的响应式系统,这种方式使得Vue3可以更好地管理组件的生命周期,在组件卸载前可以及时清理绑定的数据和事件。
The end…
如果您认真阅读至此,您现在已经掌握了的vue3与vue2的生命周期和响应式原理啦 ,为接下来我们学习Vue3更加有信心!!。
如果喜欢这个帖子,请不要忘记点赞,留言,评论。我们一起在前端小白中进步