Skip to content

Commit

Permalink
fix(watch): watch will trigger when added new keys using set (#468)
Browse files Browse the repository at this point in the history
* fix(watch): watch will trigger when added new keys using `set`

* chore: add docs

* Update README.md

Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>

* Update README.md

Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>
  • Loading branch information
pikax and antfu authored Aug 10, 2020
1 parent f7990c9 commit 13bfed1
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 1 deletion.
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,27 @@ a.list.push(
a.list[1].count === 1 // true
```

</details>

<details>
<summary>
⚠️ `set` workaround for adding new reactive properties
</summary>

> ⚠️ Warning: `set` does NOT exist in Vue 3. We provide it as a workaround here, due to the limitation of [Vue 2.x reactivity system](https://vuejs.org/v2/guide/reactivity.html#For-Objects). In Vue 2, you will need to call `set` to track new keys on an `object`(similar to `Vue.set` but for `reactive objects` created by the Composition API). In Vue 3, you can just assign them like normal objects.
```ts
import { reactive, set } from '@vue/composition-api'

const a = reactive({
foo: 1
})

// add new reactive key
set(a, 'bar', 1)
```


</details>

### Template Refs
Expand Down
16 changes: 16 additions & 0 deletions src/apis/watch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ export interface VueWatcher {
lazy: boolean
get(): any
teardown(): void
run(): void

value: any
}

export type WatchStopHandle = () => void
Expand Down Expand Up @@ -315,6 +318,19 @@ function createWatcher(

// Once again, we have to hack the watcher for proper teardown
const watcher = vm._watchers[vm._watchers.length - 1]

// if the return value is reactive and deep:true
// watch for changes, this might happen when new key is added
if (isReactive(watcher.value) && deep) {
watcher.value.__ob__.dep.addSub({
update() {
// this will force the source to be revaluated and the callback
// executed if needed
watcher.run()
},
})
}

patchWatcherTeardown(watcher, runCleanup)

return () => {
Expand Down
14 changes: 13 additions & 1 deletion test/apis/watch.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const Vue = require('vue/dist/vue.common.js')
const { ref, reactive, watch, watchEffect } = require('../../src')
const { ref, reactive, watch, watchEffect, set } = require('../../src')

describe('api/watch', () => {
const anyFn = expect.any(Function)
Expand Down Expand Up @@ -745,4 +745,16 @@ describe('api/watch', () => {
.then(done)
})
})

it('should execute watch when new key is added', () => {
const r = reactive({})

const cb = jest.fn()

watch(r, cb, { deep: true })

set(r, 'a', 1)

expect(cb).toHaveBeenCalled()
})
})

0 comments on commit 13bfed1

Please sign in to comment.