refactor(watch): adjsut watch API behavior

BREAKING CHANGE: `watch` behavior has been adjusted.

    - When using the `watch(source, callback, options?)` signature, the
      callback now fires lazily by default (consistent with 2.x
      behavior).

      Note that the `watch(effect, options?)` signature is still eager,
      since it must invoke the `effect` immediately to collect
      dependencies.

    - The `lazy` option has been replaced by the opposite `immediate`
      option, which defaults to `false`. (It's ignored when using the
      effect signature)

    - Due to the above changes, the `watch` option in Options API now
      behaves exactly the same as 2.x.

    - When using the effect signature or `{ immediate: true }`, the
      intital execution is now performed synchronously instead of
      deferred until the component is mounted. This is necessary for
      certain use cases to work properly with `async setup()` and
      Suspense.

      The side effect of this is the immediate watcher invocation will
      no longer have access to the mounted DOM. However, the watcher can
      be initiated inside `onMounted` to retain previous behavior.
This commit is contained in:
Evan You
2020-02-17 23:14:19 -05:00
parent d9d63f21b1
commit 9571ede84b
7 changed files with 176 additions and 143 deletions

View File

@@ -149,30 +149,24 @@ describe('api: options', () => {
function assertCall(spy: jest.Mock, callIndex: number, args: any[]) {
expect(spy.mock.calls[callIndex].slice(0, 2)).toMatchObject(args)
expect(spy).toHaveReturnedWith(ctx)
}
assertCall(spyA, 0, [1, undefined])
assertCall(spyB, 0, [2, undefined])
assertCall(spyC, 0, [{ qux: 3 }, undefined])
expect(spyA).toHaveReturnedWith(ctx)
expect(spyB).toHaveReturnedWith(ctx)
expect(spyC).toHaveReturnedWith(ctx)
ctx.foo++
await nextTick()
expect(spyA).toHaveBeenCalledTimes(2)
assertCall(spyA, 1, [2, 1])
expect(spyA).toHaveBeenCalledTimes(1)
assertCall(spyA, 0, [2, 1])
ctx.bar++
await nextTick()
expect(spyB).toHaveBeenCalledTimes(2)
assertCall(spyB, 1, [3, 2])
expect(spyB).toHaveBeenCalledTimes(1)
assertCall(spyB, 0, [3, 2])
ctx.baz.qux++
await nextTick()
expect(spyC).toHaveBeenCalledTimes(2)
expect(spyC).toHaveBeenCalledTimes(1)
// new and old objects have same identity
assertCall(spyC, 1, [{ qux: 4 }, { qux: 4 }])
assertCall(spyC, 0, [{ qux: 4 }, { qux: 4 }])
})
test('watch array', async () => {
@@ -218,30 +212,24 @@ describe('api: options', () => {
function assertCall(spy: jest.Mock, callIndex: number, args: any[]) {
expect(spy.mock.calls[callIndex].slice(0, 2)).toMatchObject(args)
expect(spy).toHaveReturnedWith(ctx)
}
assertCall(spyA, 0, [1, undefined])
assertCall(spyB, 0, [2, undefined])
assertCall(spyC, 0, [{ qux: 3 }, undefined])
expect(spyA).toHaveReturnedWith(ctx)
expect(spyB).toHaveReturnedWith(ctx)
expect(spyC).toHaveReturnedWith(ctx)
ctx.foo++
await nextTick()
expect(spyA).toHaveBeenCalledTimes(2)
assertCall(spyA, 1, [2, 1])
expect(spyA).toHaveBeenCalledTimes(1)
assertCall(spyA, 0, [2, 1])
ctx.bar++
await nextTick()
expect(spyB).toHaveBeenCalledTimes(2)
assertCall(spyB, 1, [3, 2])
expect(spyB).toHaveBeenCalledTimes(1)
assertCall(spyB, 0, [3, 2])
ctx.baz.qux++
await nextTick()
expect(spyC).toHaveBeenCalledTimes(2)
expect(spyC).toHaveBeenCalledTimes(1)
// new and old objects have same identity
assertCall(spyC, 1, [{ qux: 4 }, { qux: 4 }])
assertCall(spyC, 0, [{ qux: 4 }, { qux: 4 }])
})
test('provide/inject', () => {