/** vue3 响应式原理;
-
- 使用proxy设置代理
-
- 使用reactive api 收集和触发依赖
-
- mount 方法中执行effect方法
-
- effect方法中执行fn,更新页面; */
/**
- vue3 通过composition-api 的reactive api实现的响应式
- 1.mount的时候,执行effect函数,生成activeEffect;
- 2.执行setup函数,调用reactive api的时候,触发data对象的get方法,执行track方法收集依赖, 将activeEffect添加到targetMap【key】 = 【】 生成了响应式数据;
-
- 调用reactive api生成的数据改变的时候,触发set方法, 执行trigger方法触发依赖,将targetMap【key】中依赖遍历依次执行 reactiveEffect.run();
-
- 执行依赖 reactiveEffect.run()的时候,就是执行了effect的回调函数,去更新页面; */
let isObject = data => data && typeof data === "object";
let targetMap = new WeakMap();
let activeEffect = null;
// 发布订阅模式
// 收集依赖【依赖就是 ReactiveEffect实例 ,实例有两个属性: effect函数的参数、run函数】
function track(target,key) {
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());
}
trackEffect(dep);
}
function trackEffect(dep) {
if(!dep.has(activeEffect)){
dep.add(activeEffect);
}
}
function trigger(target,key) {
let depsMap = targetMap.get(target);
let dep = depsMap.get(key);
(dep || []).forEach(effect => {
effect.run();
});
}
export function reactive(data) {
return new Proxy(data, {
get(target,key,receiver){
if(!isObject(data)) return;
let ret = Reflect.get(target,key,receiver);
track(target,key);
isObject(ret) ? reactive(ret) : ret;
return ret;
},
set(target,key,value,receiver){
Reflect.set(target,key,value,receiver);
trigger(target,key);
return true;
},
deleteProperty(target,key,receiver){
let ret = Reflect.deleteProperty(target,key,receiver);
trigger(target,key);
return ret;
},
has(target,key,receiver){
let ret = Reflect.has(target,key,receiver);
track(target,key);
return ret;
},
ownKeys(target,receiver){
return Reflect.ownKeys(target,receiver);
}
})
}
function effect(fn, options = {}) {
let __effect = new ReactiveEffect(fn);
options.lazy || __effect.run();
return __effect;
}
class ReactiveEffect {
constructor(fn){
this.fn = fn;
}
run(){
activeEffect = this;
return this.fn();
}
}
export function mount(ins, el) {
effect(() => {
ins.$data && update(ins, el);
})
ins.$data = ins.setup();
update(ins,el);
function update(ins, el) {
el.innerHTML = ins.render();
}
}
export function ref(init){
class RefImpl {
constructor(init){
this.__value = init;
}
get value(){
track(this, 'value');
return this.__value;
}
set value(newVal){
this.__value = newVal;
trigger(this, 'value');
}
}
return new RefImpl(init);
}
export function computed(fn){
let __computed;
const e = effect(fn, {lazy: true});
__computed = {
get value() {
return e.run();
}
}
return __computed;
}
// diff 算法;
// vue-i18n 多语言的变量的配置:
变量属性: <div :title="${$t{'confirm'}}">
变量文本: {{ $t(${confirm})}}