js-review/js/vue响应式原理/3-activeEffect&ref.js
2024-06-01 04:29:31 +08:00

88 lines
1.8 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const targetMap = new WeakMap() // 用原始对象作为key依赖映射作为value
let activeEffect = null // 保存当前的需要订阅通知的effect
function track(target, key) {
if(activeEffect) {
let depsMap = targetMap.get(target)
if(!depsMap) {
targetMap.set(target, (depsMap = new Map()))
}
let dep = depsMap.get(key)
if(!dep){
depsMap.set(key, (dep=new Set()))
}
dep.add(activeEffect) // 将efect添加进通知set
}
}
function trigger(target, key) {
const depsMap = targetMap.get(target)
if(!depsMap) return
const deps = depsMap.get(key)
deps.forEach(effect => {
effect()
});
}
function reactive(target){
const hander = {
get(target, key, receiver) {
const result = Reflect.get(target, key, receiver)
track(target, key)
return result
},
set(target, key, value, receiver) {
let oldValue = target[key]
let result = Reflect.set(target, key, value, receiver)
if (oldValue !== value){
trigger(target, key)
}
return result
}
}
return new Proxy(target, hander)
}
// 创建ref为基本数据类型赋予响应式功能
function ref(raw) {
const r = {
get value(){
track(r, 'value')
return raw
},
set value(newVal){
raw = newVal
trigger(r, 'value')
}
}
return r
}
function effect(effect){
activeEffect = effect
activeEffect()
activeEffect = null
}
const product = new reactive({price: 5, quantity: 2})
let tax = ref(5) // 固定的商品税
let total = 0
effect(()=>{
total = tax.value + product.price * product.quantity // price和quantity都被跟踪了
})
console.log(total);
product.quantity = 4
product.price = 5
console.log(total);
tax.value = 10 // 修改固定的商品税
console.log(total);