From 14bc0186b3eab40dc6b1a832ed327fbc63256618 Mon Sep 17 00:00:00 2001 From: Eduardo San Martin Morote Date: Fri, 29 Jul 2016 22:51:42 +0200 Subject: [PATCH] Avoid defining reactive twice Fix #19 --- src/vuefire.js | 20 +++++++++++-- tests/vuefire.spec.js | 65 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 2 deletions(-) diff --git a/src/vuefire.js b/src/vuefire.js index 03d183af..31df8e19 100644 --- a/src/vuefire.js +++ b/src/vuefire.js @@ -100,6 +100,22 @@ function bind (vm, key, source) { } } +/** + * Define a reactive property in a given vm if it's not defined + * yet + * + * @param {Vue} vm + * @param {string} key + * @param {*} val + */ +function defineReactive (vm, key, val) { + if (key in vm) { + vm[key] = val + } else { + Vue.util.defineReactive(vm, key, val) + } +} + /** * Bind a firebase data source to a key on a vm as an Array. * @@ -110,7 +126,7 @@ function bind (vm, key, source) { */ function bindAsArray (vm, key, source, cancelCallback) { var array = [] - Vue.util.defineReactive(vm, key, array) + defineReactive(vm, key, array) var onAdd = source.on('child_added', function (snapshot, prevKey) { var index = prevKey ? indexForKey(array, prevKey) + 1 : 0 @@ -151,7 +167,7 @@ function bindAsArray (vm, key, source, cancelCallback) { * @param {function|null} cancelCallback */ function bindAsObject (vm, key, source, cancelCallback) { - Vue.util.defineReactive(vm, key, {}) + defineReactive(vm, key, {}) var cb = source.on('value', function (snapshot) { vm[key] = createRecord(snapshot) }, cancelCallback) diff --git a/tests/vuefire.spec.js b/tests/vuefire.spec.js index 61eeacd4..ab8b3720 100644 --- a/tests/vuefire.spec.js +++ b/tests/vuefire.spec.js @@ -86,6 +86,42 @@ describe('VueFire', function () { }) }) + it('bind using $bindAsArray after $unbind', function (done) { + var refItems = firebaseRef.child('items') + var refOther = firebaseRef.child('other') + var vm = new Vue({ + template: '
{{ item[".key"] }} {{ item.index }}
', + created: function () { + this.$bindAsArray('items', refItems) + } + }).$mount() + refItems.set({ + first: { index: 0 }, + second: { index: 1 }, + third: { index: 2 } + }, function () { + expect(vm.items).to.deep.equal([ + { '.key': 'first', index: 0 }, + { '.key': 'second', index: 1 }, + { '.key': 'third', index: 2 } + ]) + vm.$unbind('items') + vm.$bindAsArray('items', refOther) + refOther.set({ + a: { index: 0 }, + b: { index: 1 }, + c: { index: 2 } + }, function () { + expect(vm.items).to.deep.equal([ + { '.key': 'a', index: 0 }, + { '.key': 'b', index: 1 }, + { '.key': 'c', index: 2 } + ]) + done() + }) + }) + }) + it('binds array records which are primitives', function (done) { var vm = new Vue({ firebase: { @@ -531,6 +567,35 @@ describe('VueFire', function () { }) }) + it('binds with $bindAsObject after $unbind', function (done) { + var obj = { + first: { index: 0 }, + second: { index: 1 }, + third: { index: 2 } + } + var objOther = { + onlyOne: { index: 0 }, + second: { index: 1 } + } + var vm = new Vue({ + template: '
{{ items | json }}
', + created: function () { + this.$bindAsObject('items', firebaseRef.child('items')) + } + }).$mount() + firebaseRef.child('items').set(obj, function () { + obj['.key'] = 'items' + expect(vm.items).to.deep.equal(obj) + vm.$unbind('items') + vm.$bindAsObject('items', firebaseRef.child('others')) + firebaseRef.child('others').set(objOther, function () { + objOther['.key'] = 'others' + expect(vm.items).to.deep.equal(objOther) + done() + }) + }) + }) + it('binds with $bindAsObject', function (done) { var obj = { first: { index: 0 },