UNPKG

reecho

Version:

Reecho 是一款基于依赖收集的MVVM框架,它具有以下特点 - 声明式数据: 基于proxy的依赖收集 - 使用函数定义组件,但组件不会如React一样重复执行造成心智负担 - 读写分离,读取状态和更改状态统一使用函数,避免vue3的ref一样有时需要`xxx.value`有时不需要的不一致性 - 使用TS编写,类型友好

84 lines (73 loc) 2.06 kB
import { effect, trigger, track } from "./effect"; import { Ref } from "./ref"; import { isFunction } from "../shared"; import { TrackOpTypes, TriggerOpTypes } from "./operations"; // computed分为只读和可写,可写的用于setter函数 export interface ComputedRef<T = any> extends WritableComputedRef<T> { readonly value: T; } export interface WritableComputedRef<T> extends Ref<T> { readonly effect: any; } export type ComputedGetter<T> = () => T; export type ComputedSetter<T> = (v: T) => void; export interface WritableComputedOptions<T> { get: ComputedGetter<T>; set: ComputedSetter<T>; } class ComputedRefImpl<T> { private _value: T; // 确保effect只会在第一次读取computed的时被调用 private _dirty: boolean = true; public readonly effect: Function; public __readonly: boolean = true; constructor( getter: ComputedGetter<T>, readonly setter: ComputedSetter<T>, isReadonly: boolean ) { this.effect = effect(getter, { lazy: true, scheduler: () => { // 依赖追踪只进行一次 if (!this._dirty) { this._dirty = true; trigger(this, TriggerOpTypes.SET, "value"); } }, }); this.__readonly = isReadonly; } get value() { if (this._dirty) { this._value = this.effect(); this._dirty = false; } track(this, TrackOpTypes.GET, "value"); return this._value; } set value(newVal: T) { this.setter(newVal); } } export function computed<T>( getterOrOptions: ComputedGetter<T> | WritableComputedOptions<T> ): ComputedRef<T> { let getter: ComputedGetter<T>; let setter: ComputedSetter<T>; if (isFunction(getterOrOptions)) { // 参数为函数的为只读 getter = getterOrOptions; setter = () => {}; } else { // 参数为对象的为可写 getter = getterOrOptions.get; setter = getterOrOptions.set; } return new ComputedRefImpl( getter, setter, isFunction(getterOrOptions) || !(getterOrOptions as WritableComputedOptions<T>).set ); }