详解 Vue3 中如何使用 Proxy 来实现响应式的技术~
- 写在前面
- 剖析 Vue2 中是如何实现响应式的
- Vue2 的响应式存在什么问题?
- Vue3 响应式
- 一、`ref` 函数
- 二、`reactive` 函数
- `reactive` 响应式原理 - Proxy
- Vue3 中的响应式解决了 Vue2 中存在的问题
写在前面
Vue3 中的响应式原理以及实现机制,相较于 Vue2 中,有了很大的升级和性能提升。而且优化了很多问题,值得学习和研究!
学习和理解 Vue3 中的响应式原理和实现,对再项目实战中的使用,有很大的帮助;遇到问题时,能发现问题的关键所在。
剖析 Vue2 中是如何实现响应式的
我们知道,在 Vue2 中,Vue 是使用 Object.defineProperty
来实现响应式的。关于 Object.defineProperty
,一个简单的例子:
// 源数据
let person = {
name: '张三',
age: 18
}
// 模拟 Vue2 中实现响应式
let p = {}
Object.defineProperty(p, 'age', {
// enumerable:true, // 控制属性是否可以枚举,默认值是false
// writable:true, // 控制属性是否可以被修改,默认值是false
// configurable:true, // 控制属性是否可以被删除,默认值是false
//当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
get(){
console.log('【检测到了】有人读取age属性了,我可以做一些事情了,这里是响应式的关键')
return person.number
},
//当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
set(value){
console.log('【检测到了】有人修改了age属性,且值是:', value)
person.age = value
}
})
// ...
上面的例子中,使用了 Object.defineProperty
给 p
的 age
属性设置了 set
、get
方法。
这样,以后,p
的 age
属性发生修改或者取值的时候,就能监测到了。
同理,p
中的其他属性,也是这样来实现响应式的,Vue2 中就是这样做的。
Vue2 的响应式存在什么问题?
1、新增属性、删除属性、界面不会更新
Vue2 的解决方法:
this.$set(object, 'key', value)
、this.$delete(object, 'key')
2、直接通过下标修改数组,界面不会自动更新
Vue2 的解决方法:
this.$set(object, index, value)
Vue3 响应式
一、ref
函数
在 Vue3 中,定义基本数据类型的响应式,我们使用 ref
函数。
let sum = ref(0)
console.log(sum.value)
return {
sum
}
ref
函数:
- 接受的数据可以是:基本类型、也可以是对象类型;
- 基本类型的数据是:响应式依然是靠
Object.defineProperty()
的get
与set
完成的; - 对象类型的数据:内部【求助】了 Vue3 中的一个新函数 ——
reactive
函数;
二、reactive
函数
定义一个【引用类型】的响应式数据(基本类型不要用它,要用 ref
函数)
let personInfo = reactive({
name: '张三',
age: 11,
jobs: ['前端', '后端', '设计']
})
reactive
定义的响应式数据是“深层次的”。- 内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据进行操作。
reactive
响应式原理 - Proxy
- 通过 Proxy(代理) 拦截对象中任意属性的变化,包括:属性值的读写、属性的添加、属性的删除等。
- 通过 Reflect(反射)对源对象的属性进行操作。
let proxy = new Proxy(data, {
// 拦截读取属性值
get (target, prop) { // target:原对象; prop:读取的属性
console.log(`监听到了属性值${prop}被读取`)
return Reflect.get(target, prop)
},
// 拦截设置属性值或添加新属性
set (target, prop, value) { // target:原对象; prop:要修改/增加的属性 value:值
//target[prop] = value
console.log(`监听到了属性值${prop}发生变化`)
return Reflect.set(target, prop, value)
},
// 拦截删除属性
deleteProperty (target, prop) {
//return delete target[prop]
console.log(`监听到了属性值${prop}被删除`)
return Reflect.deleteProperty(target, prop)
}
})
// proxy 就是源数据 data 的响应式代理对象
proxy.name = 'tom' // 触发监听
let age = proxy.age // 触发监听
delete proxy.name // 触发监听
这种方式实现的响应式,相较于之前的
Object.defineProperty
,在代码实现了,简洁优雅了很多。
Proxy 是 ES6 中新提出的方案,也是 JS 语言后面发展的方向,在 JS 语言后续的发展上,如果有改动或者新的提议,也是会在 Proxy 上面来优化,而不太会再优化之前的
Object.defineProperty
方案了。
Vue3 中的响应式解决了 Vue2 中存在的问题
1、新增属性、删除属性、界面会更新了
proxy.page = 1
VM314:15 监听到了属性值page发生变化
新增一个 page
属性时,也会触发 set()
函数了。
2、直接通过下标修改数组,界面也会自动更新
—————————— 【正文完】——————————
前端学习交流群,想进来面基的,可以加群: 832485817,685486827;
写在最后: 约定优于配置 —— 软件开发的简约原则
——————————【完】——————————
我的:
个人网站: https://neveryu.github.io/neveryu/
Github: https://github.com/Neveryu
微信: miracle421354532
更多学习资源请关注我的微信…好吗