Vue3.0 响应式原理

vue 3.0 响应式系统的升级

使用Proxy对象 重写响应式系统

  1. 可以监听动态新增的属性
  2. 可以监听删除的属性
  3. 可以监听数组的索引和length属性

响应式核心函数

  1. reactive/ref/toRefs/computed
  2. effect
  3. track 手机依赖
  4. 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 更新依赖

Vue3.0 响应式原理

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

  1. ref 可以把基本数据类型,转成响应式对象
  2. ref 返回对象,重新赋值成对象也是响应式的
  3. reactive 返回的对象,重新赋值丢失响应式
  4. 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)
上一篇:Vue3基础知识学习


下一篇:认识Vue3 了解相关信息