mirror of https://github.com/vuejs/vue.git
refactory: computed react
This commit is contained in:
parent
9e88707940
commit
8363aee6bb
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue