Browse Source

wip: adjust watcher cleanup api

Evan You 7 years ago
parent
commit
d3fe492d7e
2 changed files with 30 additions and 42 deletions
  1. 4 15
      packages/observer/__tests__/computed.spec.ts
  2. 26 27
      packages/runtime-core/src/reactivity.ts

+ 4 - 15
packages/observer/__tests__/computed.spec.ts

@@ -37,21 +37,6 @@ describe('observer/computed', () => {
     expect(getter).toHaveBeenCalledTimes(2)
   })
 
-  it('should accept context', () => {
-    const value: any = observable({})
-    let callCtx, callArg
-    const getter = function(arg: any) {
-      callCtx = this
-      callArg = arg
-      return value.foo
-    }
-    const ctx = {}
-    const cValue = computed(getter, ctx)
-    cValue.value
-    expect(callCtx).toBe(ctx)
-    expect(callArg).toBe(ctx)
-  })
-
   it('should trigger effect', () => {
     const value: any = observable({})
     const cValue = computed(() => value.foo)
@@ -136,4 +121,8 @@ describe('observer/computed', () => {
     value.foo = 2
     expect(dummy).toBe(1)
   })
+
+  it('should support setter', () => {
+    // TODO
+  })
 })

+ 26 - 27
packages/runtime-core/src/reactivity.ts

@@ -31,7 +31,7 @@ import {
 } from '@vue/observer'
 import { currentInstance } from './component'
 import { queueJob, queuePostFlushCb } from './scheduler'
-import { EMPTY_OBJ, isObject, isArray, isFunction } from '@vue/shared'
+import { EMPTY_OBJ, isObject, isArray } from '@vue/shared'
 
 // record effects created during a component's setup() so that they can be
 // stopped when the component unmounts
@@ -63,39 +63,38 @@ const invoke = (fn: Function) => fn()
 
 export function watch<T>(
   source: Value<T> | (() => T),
-  cb?: <V extends T>(newValue: V, oldValue: V) => (() => void) | void,
-  options: WatchOptions = EMPTY_OBJ
+  cb?: <V extends T>(
+    newValue: V,
+    oldValue: V,
+    onInvalidate: (fn: () => void) => void
+  ) => any | void,
+  { lazy, flush, deep, onTrack, onTrigger }: WatchOptions = EMPTY_OBJ
 ): () => void {
   const scheduler =
-    options.flush === 'sync'
-      ? invoke
-      : options.flush === 'pre'
-        ? queueJob
-        : queuePostFlushCb
+    flush === 'sync' ? invoke : flush === 'pre' ? queueJob : queuePostFlushCb
 
   const baseGetter = isValue(source) ? () => source.value : source
-  const getter = options.deep ? () => traverse(baseGetter()) : baseGetter
+  const getter = deep ? () => traverse(baseGetter()) : baseGetter
 
-  let oldValue: any
   let cleanup: any
+  const registerCleanup = (fn: () => void) => {
+    // TODO wrap the cleanup fn for error handling
+    cleanup = runner.onStop = fn
+  }
+
+  let oldValue: any
   const applyCb = cb
     ? () => {
         const newValue = runner()
-        if (options.deep || newValue !== oldValue) {
-          try {
-            // cleanup before running cb again
-            if (cleanup) {
-              cleanup()
-            }
-            const _cleanup = cb(newValue, oldValue)
-            if (isFunction(_cleanup)) {
-              // save cleanup so it is also called when effect is stopped
-              cleanup = runner.onStop = _cleanup
-            }
-          } catch (e) {
-            // TODO handle error
-            // handleError(e, instance, ErrorTypes.WATCH_CALLBACK)
+        if (deep || newValue !== oldValue) {
+          // cleanup before running cb again
+          if (cleanup) {
+            cleanup()
           }
+          // TODO handle error (including ASYNC)
+          try {
+            cb(newValue, oldValue, registerCleanup)
+          } catch (e) {}
           oldValue = newValue
         }
       }
@@ -105,12 +104,12 @@ export function watch<T>(
     lazy: true,
     // so it runs before component update effects in pre flush mode
     computed: true,
-    onTrack: options.onTrack,
-    onTrigger: options.onTrigger,
+    onTrack,
+    onTrigger,
     scheduler: applyCb ? () => scheduler(applyCb) : void 0
   })
 
-  if (!options.lazy) {
+  if (!lazy) {
     applyCb && scheduler(applyCb)
   } else {
     oldValue = runner()