refactory: computed react

This commit is contained in:
kwy404 2025-01-24 15:08:58 -03:00
parent 9e88707940
commit 8363aee6bb
1 changed files with 40 additions and 61 deletions

View File

@ -1,100 +1,79 @@
import { isServerRendering, noop, warn, def, isFunction } from 'core/util' import { isServerRendering, noop, warn, def, isFunction } from 'core/util';
import { Ref, RefFlag } from './ref' import { Ref, RefFlag } from './ref';
import Watcher from 'core/observer/watcher' import Watcher from 'core/observer/watcher';
import Dep from 'core/observer/dep' import Dep from 'core/observer/dep';
import { currentInstance } from '../currentInstance' import { currentInstance } from '../currentInstance';
import { ReactiveFlags } from './reactive' import { ReactiveFlags } from './reactive';
import { TrackOpTypes } from './operations' import { TrackOpTypes } from './operations';
import { DebuggerOptions } from '../debug' import { DebuggerOptions } from '../debug';
declare const ComputedRefSymbol: unique symbol declare const ComputedRefSymbol: unique symbol;
export interface ComputedRef<T = any> extends WritableComputedRef<T> { export interface ComputedRef<T = any> extends WritableComputedRef<T> {
readonly value: T readonly value: T;
[ComputedRefSymbol]: true [ComputedRefSymbol]: true;
} }
export interface WritableComputedRef<T> extends Ref<T> { export interface WritableComputedRef<T> extends Ref<T> {
readonly effect: any /* Watcher */ readonly effect: any /* Watcher */;
} }
export type ComputedGetter<T> = (...args: any[]) => T export type ComputedGetter<T> = () => T;
export type ComputedSetter<T> = (v: T) => void export type ComputedSetter<T> = (v: T) => void;
export interface WritableComputedOptions<T> { export interface WritableComputedOptions<T> {
get: ComputedGetter<T> get: ComputedGetter<T>;
set: ComputedSetter<T> set: ComputedSetter<T>;
} }
export function computed<T>(
getter: ComputedGetter<T>,
debugOptions?: DebuggerOptions
): ComputedRef<T>
export function computed<T>(
options: WritableComputedOptions<T>,
debugOptions?: DebuggerOptions
): WritableComputedRef<T>
export function computed<T>( export function computed<T>(
getterOrOptions: ComputedGetter<T> | WritableComputedOptions<T>, getterOrOptions: ComputedGetter<T> | WritableComputedOptions<T>,
debugOptions?: DebuggerOptions debugOptions?: DebuggerOptions
) { ): ComputedRef<T> | WritableComputedRef<T> {
let getter: ComputedGetter<T> const isGetterOnly = isFunction(getterOrOptions);
let setter: ComputedSetter<T> const getter = isGetterOnly ? getterOrOptions : getterOrOptions.get;
const setter = isGetterOnly
const onlyGetter = isFunction(getterOrOptions) ? (__DEV__
if (onlyGetter) { ? () => warn('Write operation failed: computed value is readonly')
getter = getterOrOptions : noop)
setter = __DEV__ : getterOrOptions.set;
? () => {
warn('Write operation failed: computed value is readonly')
}
: noop
} else {
getter = getterOrOptions.get
setter = getterOrOptions.set
}
const watcher = isServerRendering() const watcher = isServerRendering()
? null ? null
: new Watcher(currentInstance, getter, noop, { lazy: true }) : new Watcher(currentInstance, getter, noop, { lazy: true });
if (__DEV__ && watcher && debugOptions) { if (__DEV__ && watcher && debugOptions) {
watcher.onTrack = debugOptions.onTrack watcher.onTrack = debugOptions.onTrack;
watcher.onTrigger = debugOptions.onTrigger watcher.onTrigger = debugOptions.onTrigger;
} }
const ref = { const ref = {
// some libs rely on the presence effect for checking computed refs
// from normal refs, but the implementation doesn't matter
effect: watcher, effect: watcher,
get value() { get value() {
if (watcher) { if (watcher) {
if (watcher.dirty) { if (watcher.dirty) watcher.evaluate();
watcher.evaluate()
}
if (Dep.target) { if (Dep.target) {
if (__DEV__ && Dep.target.onTrack) { if (__DEV__ && Dep.target.onTrack) {
Dep.target.onTrack({ Dep.target.onTrack({
effect: Dep.target, effect: Dep.target,
target: ref, target: ref,
type: TrackOpTypes.GET, type: TrackOpTypes.GET,
key: 'value' key: 'value',
}) });
} }
watcher.depend() watcher.depend();
} }
return watcher.value return watcher.value;
} else {
return getter()
} }
return getter();
}, },
set value(newVal) { set value(newValue: T) {
setter(newVal) setter(newValue);
} },
} as any } as WritableComputedRef<T>;
def(ref, RefFlag, true) def(ref, RefFlag, true);
def(ref, ReactiveFlags.IS_READONLY, onlyGetter) def(ref, ReactiveFlags.IS_READONLY, isGetterOnly);
return ref return ref;
} }