91 lines
1.8 KiB
JavaScript
91 lines
1.8 KiB
JavaScript
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
|
||
}
|
||
|
||
function computed(getter){
|
||
let result = ref()
|
||
effect(()=>(result.value = getter()))
|
||
return result
|
||
}
|
||
|
||
const product = new reactive({price: 5, quantity: 2})
|
||
|
||
const total = computed(()=>{
|
||
return product.price * product.quantity
|
||
})
|
||
|
||
console.log(total.value);
|
||
product.price = 3
|
||
console.log(total.value);
|
||
product.quantity = 10
|
||
console.log(total.value);
|
||
|