mirror of
https://gitee.com/vuejs/vue.git
synced 2024-11-30 02:57:43 +08:00
refactor: simplify implementations
since we output es5, classes are more verbose then necessary
This commit is contained in:
parent
282ebb0893
commit
a16271280a
@ -13,7 +13,7 @@ export interface ComputedRef<T = any> extends WritableComputedRef<T> {
|
||||
}
|
||||
|
||||
export interface WritableComputedRef<T> extends Ref<T> {
|
||||
readonly effect: { stop(): void }
|
||||
readonly effect: Watcher
|
||||
}
|
||||
|
||||
export type ComputedGetter<T> = (...args: any[]) => T
|
||||
@ -53,54 +53,31 @@ export function computed<T>(
|
||||
setter = getterOrOptions.set
|
||||
}
|
||||
|
||||
return new ComputedRefImpl(
|
||||
getter,
|
||||
setter,
|
||||
onlyGetter,
|
||||
isServerRendering()
|
||||
) as any
|
||||
}
|
||||
const watcher = isServerRendering()
|
||||
? null
|
||||
: new Watcher(currentInstance, getter, noop, { lazy: true })
|
||||
|
||||
class ComputedRefImpl<T> {
|
||||
public dep?: Dep = undefined
|
||||
|
||||
public readonly __v_isRef = true
|
||||
public readonly effect
|
||||
|
||||
private _watcher: Watcher | null
|
||||
|
||||
constructor(
|
||||
private _getter: ComputedGetter<T>,
|
||||
private readonly _setter: ComputedSetter<T>,
|
||||
public readonly __v_isReadonly: boolean,
|
||||
isSSR: boolean
|
||||
) {
|
||||
const watcher = (this._watcher = isSSR
|
||||
? null
|
||||
: new Watcher(currentInstance, _getter, noop, { lazy: true }))
|
||||
this.effect = {
|
||||
stop() {
|
||||
watcher && watcher.teardown()
|
||||
return {
|
||||
__v_isRef: true,
|
||||
__v_isReadonly: onlyGetter,
|
||||
// some libs rely on the presence effect for checking computed refs
|
||||
// from normal refs, but the implementation doesn't matter
|
||||
effect: watcher,
|
||||
get value() {
|
||||
if (watcher) {
|
||||
if (watcher.dirty) {
|
||||
watcher.evaluate()
|
||||
}
|
||||
if (Dep.target) {
|
||||
watcher.depend()
|
||||
}
|
||||
return watcher.value
|
||||
} else {
|
||||
return getter()
|
||||
}
|
||||
},
|
||||
set value(newVal) {
|
||||
setter(newVal)
|
||||
}
|
||||
}
|
||||
|
||||
get value() {
|
||||
const watcher = this._watcher
|
||||
if (watcher) {
|
||||
if (watcher.dirty) {
|
||||
watcher.evaluate()
|
||||
}
|
||||
if (Dep.target) {
|
||||
watcher.depend()
|
||||
}
|
||||
return watcher.value
|
||||
} else {
|
||||
return this._getter()
|
||||
}
|
||||
}
|
||||
|
||||
set value(newValue: T) {
|
||||
this._setter(newValue)
|
||||
}
|
||||
} as any
|
||||
}
|
||||
|
@ -76,33 +76,21 @@ export type CustomRefFactory<T> = (
|
||||
set: (value: T) => void
|
||||
}
|
||||
|
||||
class CustomRefImpl<T> {
|
||||
public dep = new Dep()
|
||||
private readonly _get: ReturnType<CustomRefFactory<T>>['get']
|
||||
private readonly _set: ReturnType<CustomRefFactory<T>>['set']
|
||||
|
||||
public readonly __v_isRef = true
|
||||
|
||||
constructor(factory: CustomRefFactory<T>) {
|
||||
const { get, set } = factory(
|
||||
() => this.dep.depend(),
|
||||
() => this.dep.notify()
|
||||
)
|
||||
this._get = get
|
||||
this._set = set
|
||||
}
|
||||
|
||||
get value() {
|
||||
return this._get()
|
||||
}
|
||||
|
||||
set value(newVal) {
|
||||
this._set(newVal)
|
||||
}
|
||||
}
|
||||
|
||||
export function customRef<T>(factory: CustomRefFactory<T>): Ref<T> {
|
||||
return new CustomRefImpl(factory) as any
|
||||
const dep = new Dep()
|
||||
const { get, set } = factory(
|
||||
() => dep.depend(),
|
||||
() => dep.notify()
|
||||
)
|
||||
return {
|
||||
__v_isRef: true,
|
||||
get value() {
|
||||
return get()
|
||||
},
|
||||
set value(newVal) {
|
||||
set(newVal)
|
||||
}
|
||||
} as any
|
||||
}
|
||||
|
||||
export type ToRefs<T = any> = {
|
||||
@ -120,25 +108,6 @@ export function toRefs<T extends object>(object: T): ToRefs<T> {
|
||||
return ret
|
||||
}
|
||||
|
||||
class ObjectRefImpl<T extends object, K extends keyof T> {
|
||||
public readonly __v_isRef = true
|
||||
|
||||
constructor(
|
||||
private readonly _object: T,
|
||||
private readonly _key: K,
|
||||
private readonly _defaultValue?: T[K]
|
||||
) {}
|
||||
|
||||
get value() {
|
||||
const val = this._object[this._key]
|
||||
return val === undefined ? (this._defaultValue as T[K]) : val
|
||||
}
|
||||
|
||||
set value(newVal) {
|
||||
this._object[this._key] = newVal
|
||||
}
|
||||
}
|
||||
|
||||
export type ToRef<T> = IfAny<T, Ref<T>, [T] extends [Ref] ? T : Ref<T>>
|
||||
|
||||
export function toRef<T extends object, K extends keyof T>(
|
||||
@ -158,9 +127,19 @@ export function toRef<T extends object, K extends keyof T>(
|
||||
defaultValue?: T[K]
|
||||
): ToRef<T[K]> {
|
||||
const val = object[key]
|
||||
return isRef(val)
|
||||
? val
|
||||
: (new ObjectRefImpl(object, key, defaultValue) as any)
|
||||
if (isRef(val)) {
|
||||
return val as any
|
||||
}
|
||||
return {
|
||||
__v_isRef: true,
|
||||
get value() {
|
||||
const val = object[key]
|
||||
return val === undefined ? (defaultValue as T[K]) : val
|
||||
},
|
||||
set value(newVal) {
|
||||
object[key] = newVal
|
||||
}
|
||||
} as any
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -131,7 +131,7 @@ describe('reactivity/computed', () => {
|
||||
expect(dummy).toBe(undefined)
|
||||
value.foo = 1
|
||||
expect(dummy).toBe(1)
|
||||
cValue.effect.stop()
|
||||
cValue.effect.teardown()
|
||||
value.foo = 2
|
||||
expect(dummy).toBe(1)
|
||||
})
|
||||
@ -221,7 +221,7 @@ describe('reactivity/computed', () => {
|
||||
|
||||
it('should expose value when stopped', () => {
|
||||
const x = computed(() => 1)
|
||||
x.effect.stop()
|
||||
x.effect.teardown()
|
||||
expect(x.value).toBe(1)
|
||||
})
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user