← 返回首页
响应式系统的延伸和扩展
发表时间:2024-01-08 14:15:04
响应式系统的延伸和扩展

响应式系统的延伸和扩展

1.响应式系统的延伸和扩展

我们在上小节的响应式实现代码基础上,模拟实现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