wip: computed
This commit is contained in:
parent
02421dbe62
commit
cf86e32575
0
packages/observer/__tests__/value.spec.ts
Normal file
0
packages/observer/__tests__/value.spec.ts
Normal file
@ -1,15 +1,16 @@
|
||||
import { effect } from './index'
|
||||
import { ReactiveEffect, activeReactiveEffectStack } from './effect'
|
||||
import { knownValues } from './value'
|
||||
|
||||
export interface ComputedGetter<T = any> {
|
||||
(): T
|
||||
effect: ReactiveEffect
|
||||
export interface ComputedValue<T> {
|
||||
readonly value: T
|
||||
readonly effect: ReactiveEffect
|
||||
}
|
||||
|
||||
export function computed<T, C = null>(
|
||||
getter: (this: C, ctx: C) => T,
|
||||
context?: C
|
||||
): ComputedGetter<T> {
|
||||
): ComputedValue<T> {
|
||||
let dirty: boolean = true
|
||||
let value: any = undefined
|
||||
const runner = effect(() => getter.call(context, context), {
|
||||
@ -18,7 +19,12 @@ export function computed<T, C = null>(
|
||||
dirty = true
|
||||
}
|
||||
})
|
||||
const computedGetter = (() => {
|
||||
// mark effect as computed so that it gets priority during trigger
|
||||
runner.computed = true
|
||||
const computedValue = {
|
||||
// expose effect so computed can be stopped
|
||||
effect: runner,
|
||||
get value() {
|
||||
if (dirty) {
|
||||
value = runner()
|
||||
dirty = false
|
||||
@ -28,12 +34,10 @@ export function computed<T, C = null>(
|
||||
// This should also apply for chained computed properties.
|
||||
trackChildRun(runner)
|
||||
return value
|
||||
}) as ComputedGetter
|
||||
// expose effect so computed can be stopped
|
||||
computedGetter.effect = runner
|
||||
// mark effect as computed so that it gets priority during trigger
|
||||
runner.computed = true
|
||||
return computedGetter
|
||||
}
|
||||
}
|
||||
knownValues.add(computedValue)
|
||||
return computedValue
|
||||
}
|
||||
|
||||
function trackChildRun(childRunner: ReactiveEffect) {
|
||||
|
@ -26,9 +26,9 @@ import {
|
||||
|
||||
export { ReactiveEffect, ReactiveEffectOptions, DebuggerEvent }
|
||||
export { OperationTypes } from './operations'
|
||||
export { computed, ComputedGetter } from './computed'
|
||||
export { computed, ComputedValue } from './computed'
|
||||
export { lock, unlock } from './lock'
|
||||
export { value, isValue } from './value'
|
||||
export { value, isValue, Value } from './value'
|
||||
|
||||
const collectionTypes: Set<any> = new Set([Set, Map, WeakMap, WeakSet])
|
||||
const observableValueRE = /^\[object (?:Object|Array|Map|Set|WeakMap|WeakSet)\]$/
|
||||
|
@ -1,20 +1,25 @@
|
||||
import { track, trigger } from './effect'
|
||||
import { OperationTypes } from './operations'
|
||||
import { isObject } from '@vue/shared'
|
||||
import { observable } from './index'
|
||||
|
||||
const knownValues = new WeakSet()
|
||||
export const knownValues = new WeakSet()
|
||||
|
||||
export interface Value<T> {
|
||||
value: T
|
||||
}
|
||||
|
||||
const convert = (val: any): any => (isObject(val) ? observable(val) : val)
|
||||
|
||||
export function value<T>(raw: T): Value<T> {
|
||||
raw = convert(raw)
|
||||
const v = {
|
||||
get value() {
|
||||
track(v, OperationTypes.GET, '')
|
||||
return raw
|
||||
},
|
||||
set value(newVal) {
|
||||
raw = newVal
|
||||
raw = convert(newVal)
|
||||
trigger(v, OperationTypes.SET, '')
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user