]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: computed
authorEvan You <yyx990803@gmail.com>
Wed, 29 May 2019 10:44:50 +0000 (18:44 +0800)
committerEvan You <yyx990803@gmail.com>
Wed, 29 May 2019 10:44:50 +0000 (18:44 +0800)
packages/observer/__tests__/value.spec.ts [new file with mode: 0644]
packages/observer/src/computed.ts
packages/observer/src/index.ts
packages/observer/src/value.ts

diff --git a/packages/observer/__tests__/value.spec.ts b/packages/observer/__tests__/value.spec.ts
new file mode 100644 (file)
index 0000000..e69de29
index b74f8ca54edbc536bfcc4796202325c307903272..5a517f780b523e34ee5ee053a9744e91d3c3e076 100644 (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,22 +19,25 @@ export function computed<T, C = null>(
       dirty = true
     }
   })
-  const computedGetter = (() => {
-    if (dirty) {
-      value = runner()
-      dirty = false
-    }
-    // When computed effects are accessed in a parent effect, the parent
-    // should track all the dependencies the computed property has tracked.
-    // 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
+  const computedValue = {
+    // expose effect so computed can be stopped
+    effect: runner,
+    get value() {
+      if (dirty) {
+        value = runner()
+        dirty = false
+      }
+      // When computed effects are accessed in a parent effect, the parent
+      // should track all the dependencies the computed property has tracked.
+      // This should also apply for chained computed properties.
+      trackChildRun(runner)
+      return value
+    }
+  }
+  knownValues.add(computedValue)
+  return computedValue
 }
 
 function trackChildRun(childRunner: ReactiveEffect) {
index 35b13ec3981f2655ac6c449f3b92d66ac85ab25f..423126fc1caa460769c6d2b65021cd0760568b79 100644 (file)
@@ -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)\]$/
index b37e100c20658a878a8c7a8dbde5560b723e20e0..534ee352ad57e8e4b69b3523cc0ff17856428466 100644 (file)
@@ -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, '')
     }
   }