vue 3.0 响应式系统的升级
使用Proxy对象 重写响应式系统
- 可以监听动态新增的属性
- 可以监听删除的属性
- 可以监听数组的索引和length属性
响应式核心函数
- reactive/ref/toRefs/computed
- effect
- track 手机依赖
- trigger 更新依赖
Proxy 对象中的两个小问题
第一个问题: set 和 deleteProperty 需要返回布尔类型的值
第二个问题:Proxy 和 Reflect 使用 receiver
Proxy 中的 receiver: Proxy 或者继承 Proxy 的对象
Reflect 中的receiver:如果 target对象设置了getter,getter中的this指向 receiver
const obj = {
get foo() {
console.log(this)
return this.bar
}
}
const proxy = new Proxy(obj, {
get (target, key, receiver) {
if (key === 'bar') {
console.log('value - bar')
}
return Reflect.get(target, key, receiver)
},
set (target, key, value, receiver) {
return Reflect.set(target, key, value, receiver),
deleteProperty(target, key) {
return Reflect.deleteProperty(target, key)
}
}
})
console.log(proxy.foo)
// Proxy {}
// value - bar
track 收集依赖 和 trigger 更新依赖
let activeEffect = null
export function effect (callback) {
activeEffect = callback
callback() // 访问响应式对象,收集依赖
activeEffect = null
}
let targetMap = new WeakMap()
export function track (target, key) {
if (!activeEffect) return
let depsMap = targetMap.get(target)
if (!depsMap) {
depsMap.set(key, (depsMap = new Map()))
}
let dep = depsMap.get(key)
if (!dep){
depsMap.set(key, (dep = new Set()))
}
}
export function (target, key) {
let depsMap = targetMap.get(target)
if (!depsMap) return
let dep = depsMap.get(key)
dep && dep.forEach((effect) => {
effect()
})
}
reactive VS ref
- ref 可以把基本数据类型,转成响应式对象
- ref 返回对象,重新赋值成对象也是响应式的
- reactive 返回的对象,重新赋值丢失响应式
- reactive 返回的对象不可以解构
toRefs
接收一个 reactive 返回的响应式对象
如果传入的参数不是 reactive 返回的响应式对象(__v__isRef),直接返回
然后再把传入对象挂载到一个新的对象返回
可以对对象进行解构
import { reactive, effect, toRefs } from './reactivity.js '
function useProduct () {
const product = reactive({
name: 'iPhone',
price: 5000,
count: 3
})
return toRefs(product)
}
const {price, count} = useProduct()
let total = 0
effect(() => {
total = price.value * count.value
})
console.log(total)
price.value = 4000
console.log(total)