Skip to content

Commit 4804381

Browse files
committed
feat(unbind): unsubscribe when vm is destroyed
1 parent 7ffb305 commit 4804381

File tree

5 files changed

+143
-2
lines changed

5 files changed

+143
-2
lines changed

package-lock.json

Lines changed: 104 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"nyc": "^11.3.0",
5050
"rollup": "^0.51.1",
5151
"rollup-plugin-buble": "^0.17.0",
52+
"sinon": "^4.1.2",
5253
"uglify-js": "^3.1.8",
5354
"vue": "^2.5.3"
5455
},

src/index.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,29 +67,39 @@ function bindDocument ({
6767
}
6868

6969
function bind ({ vm, key, ref }) {
70+
let unbind
7071
if (ref.add) {
71-
bindCollection({
72+
unbind = bindCollection({
7273
vm,
7374
key,
7475
collection: ref,
7576
})
7677
} else {
77-
bindDocument({
78+
unbind = bindDocument({
7879
vm,
7980
key,
8081
document: ref,
8182
})
8283
}
84+
vm._firestoreUnbinds[key] = unbind
8385
}
8486

8587
function install (Vue, options) {
8688
Vue.mixin({
8789
created () {
8890
const { firestore } = this.$options
91+
this._firestoreUnbinds = Object.create(null)
8992
if (!firestore) return
9093
Object.keys(firestore).forEach(key => {
9194
this.$bind(key, firestore[key])
9295
})
96+
},
97+
98+
beforeDestroy () {
99+
Object.values(this._firestoreUnbinds).forEach(unbind => {
100+
unbind()
101+
})
102+
this._firestoreUnbinds = null
93103
}
94104
})
95105

@@ -101,6 +111,13 @@ function install (Vue, options) {
101111
ref,
102112
})
103113
}
114+
115+
Vue.prototype.$unbind = function (key) {
116+
unbind({
117+
vm: this,
118+
key,
119+
})
120+
}
104121
}
105122

106123
export default install

test/collection.spec.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import test from 'ava'
2+
import sinon from 'sinon'
23
import Vuefire from '../src'
34
import {
45
createSnapshot
@@ -55,3 +56,19 @@ test('add properties', async t => {
5556
await doc.update({ other: 'bar' })
5657
t.deepEqual(t.context.vm.items[0], { text: 'foo', other: 'bar' })
5758
})
59+
60+
test('unbinds when the instance is destroyed', async t => {
61+
const vm = t.context.vm
62+
t.truthy(vm._firestoreUnbinds)
63+
t.deepEqual(t.context.vm.items, [])
64+
const spy = sinon.spy(vm._firestoreUnbinds, 'items')
65+
t.notThrows(() => {
66+
vm.$destroy()
67+
})
68+
t.is(spy.callCount, 1)
69+
t.is(vm._firestoreUnbinds, null)
70+
await t.notThrows(async () => {
71+
await t.context.collection.add({ text: 'foo' })
72+
t.deepEqual(t.context.vm.items, [])
73+
})
74+
})

test/helpers/mock.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class DocumentReference {
4141
onSnapshot (cb, onError) {
4242
this.cb = cb
4343
this.onError = onError
44+
return () => this.cb = this.onError = noop
4445
}
4546

4647

@@ -64,6 +65,7 @@ class CollectionReference {
6465
onSnapshot (cb, onError) {
6566
this.cb = cb
6667
this.onError = onError
68+
return () => this.cb = this.onError = noop
6769
}
6870

6971
async add (data) {

0 commit comments

Comments
 (0)