响应式系统的延伸和扩展
我们在上小节的响应式实现代码基础上,模拟实现vue3的ref,computed功能。
本小节代码结构图如下:

1).实现ref功能
ref.js
import {track,trigger} from "./effect.js";
import {TrackTypes} from "./operations.js";
import {TriggerTypes} from "./operations.js";
export function ref(value){
return{
get value(){
//依赖收集
track(this,TrackTypes.GET,'value');
return value;
},
set value(newValue) {
value = newValue;
//派发更新
trigger(this, TriggerTypes.SET, 'value');
}
}
}
测试index.js
import {reactive} from './reactive.js'
import {effect} from "./effect.js";
import {ref} from "./ref.js";
import {computed} from "./computed.js";
//测试ref.js
const state = ref(100);
effect(()=>{
console.log('effect',state.value);
})
state.value++;
运行结果:
effect 100
effect 101
2).实现computed功能
computed.js
import { effect, track, trigger } from './effect.js';
import { TrackTypes, TriggerTypes } from './operations.js';
//参数归一化,无论是函数还是对象通通变成对象。
function normalizeParameter(getterOrOptions) {
let getter, setter;
if (typeof getterOrOptions === 'function') {
getter = getterOrOptions;
setter = () => {
console.warn(`Computed property was assigned to but it has no setter.`);
};
} else {
getter = getterOrOptions.get;
setter = getterOrOptions.set;
}
return { getter, setter };
}
export function computed(getterOrOptions) {
const { getter, setter } = normalizeParameter(getterOrOptions);
let value,
dirty = true;
const effetcFn = effect(getter, {
lazy: true,
scheduler() {
dirty = true;
trigger(obj, TriggerTypes.SET, 'value');
},
});
const obj = {
get value() {
track(obj, TrackTypes.GET, 'value');
if (dirty) {
value = effetcFn();
dirty = false;
}
return value;
},
set value(newValue) {
setter(newValue);
},
};
return obj;
}
测试index.js
import {reactive} from './reactive.js'
import {effect} from "./effect.js";
import {ref} from "./ref.js";
import {computed} from "./computed.js";
//测试computed.js
const state = reactive({
x: 10,
y: 7
})
const sum = computed(()=>{
console.log('computed')
return state.x+state.y;
})
console.log(sum.value);
state.x = 100;
console.log(sum.value);
console.log(sum.value);//测试计算属性是否使用了缓存
console.log(sum.value);//测试计算属性是否使用了缓存
console.log(sum.value);//测试计算属性是否使用了缓存
运行结果:
computed
17
computed
107
107
107
107