make primitive arrays work with computed property

This commit is contained in:
Evan You 2014-03-03 10:13:46 -05:00
parent bcc965b337
commit 8d65a078f3
3 changed files with 39 additions and 18 deletions

View File

@ -93,6 +93,7 @@ module.exports = {
var self = this var self = this
this.mutationListener = function (path, arr, mutation) { this.mutationListener = function (path, arr, mutation) {
if (self.lock) return
var method = mutation.method var method = mutation.method
mutationHandlers[method].call(self, mutation) mutationHandlers[method].call(self, mutation)
if (method !== 'push' && method !== 'pop') { if (method !== 'push' && method !== 'pop') {
@ -213,15 +214,15 @@ module.exports = {
*/ */
build: function (data, index) { build: function (data, index) {
var ctn = this.container, var self = this,
vms = this.vms, ctn = self.container,
col = this.collection, vms = self.vms,
el, oldIndex, existing, item, nonObject el, oldIndex, existing, item, nonObject
// get our DOM insertion reference node // get our DOM insertion reference node
var ref = vms.length > index var ref = vms.length > index
? vms[index].$el ? vms[index].$el
: this.ref : self.ref
// if reference VM is detached by v-if, // if reference VM is detached by v-if,
// use its v-if ref node instead // use its v-if ref node instead
@ -230,13 +231,13 @@ module.exports = {
} }
// check if data already exists in the old array // check if data already exists in the old array
oldIndex = this.old ? indexOf(this.old, data) : -1 oldIndex = self.old ? indexOf(self.old, data) : -1
existing = oldIndex > -1 existing = oldIndex > -1
if (existing) { if (existing) {
// existing, reuse the old VM // existing, reuse the old VM
item = this.oldVMs[oldIndex] item = self.oldVMs[oldIndex]
// mark, so it won't be destroyed // mark, so it won't be destroyed
item.$reused = true item.$reused = true
@ -246,7 +247,7 @@ module.exports = {
// there's some preparation work to do... // there's some preparation work to do...
// first clone the template node // first clone the template node
el = this.el.cloneNode(true) el = self.el.cloneNode(true)
// then we provide the parentNode for v-if // then we provide the parentNode for v-if
// so that it can still work in a detached state // so that it can still work in a detached state
el.vue_if_parent = ctn el.vue_if_parent = ctn
@ -260,10 +261,10 @@ module.exports = {
// index instead of undefined // index instead of undefined
data.$index = index data.$index = index
// initialize the new VM // initialize the new VM
item = new this.Ctor({ item = new self.Ctor({
el : el, el : el,
data : data, data : data,
parent : this.vm, parent : self.vm,
compilerOptions: { compilerOptions: {
repeat: true repeat: true
} }
@ -271,10 +272,10 @@ module.exports = {
// for non-object values, listen for value change // for non-object values, listen for value change
// so we can sync it back to the original Array // so we can sync it back to the original Array
if (nonObject) { if (nonObject) {
item.$compiler.observer.on('set', function (key, val) { item.$compiler.observer.on('change:$value', function (val) {
if (key === '$value') { self.lock = true
col[item.$index] = val self.collection.set(item.$index, val)
} self.lock = false
}) })
} }
@ -295,7 +296,7 @@ module.exports = {
ctn.insertBefore(el.parentNode ? el : el.vue_if_ref, ref) ctn.insertBefore(el.parentNode ? el : el.vue_if_ref, ref)
} else { } else {
if (el.vue_if !== false) { if (el.vue_if !== false) {
if (this.compiler.init) { if (self.compiler.init) {
// do not transition on initial compile, // do not transition on initial compile,
// just manually insert. // just manually insert.
ctn.insertBefore(el, ref) ctn.insertBefore(el, ref)

View File

@ -60,15 +60,18 @@ function watchMutation (method) {
inserted = args.slice(2) inserted = args.slice(2)
removed = result removed = result
} }
// link & unlink // link & unlink
linkArrayElements(this, inserted) linkArrayElements(this, inserted)
unlinkArrayElements(this, removed) unlinkArrayElements(this, removed)
// emit the mutation event // emit the mutation event
this.__emitter__.emit('mutate', null, this, { this.__emitter__.emit('mutate', null, this, {
method: method, method : method,
args: args, args : args,
result: result result : result,
inserted : inserted,
removed : removed
}) })
return result return result

View File

@ -746,16 +746,33 @@ describe('UNIT: Directives', function () {
} }
}) })
it('should work with primitive values', function () { it('should work with primitive values', function (done) {
var triggeredChange = 0
var v = new Vue({ var v = new Vue({
template: '<span v-repeat="tags" v-ref="tags">{{$value}}</span>', template: '<span v-repeat="tags" v-ref="tags">{{$value}}</span>',
data: { data: {
tags: ['a', 'b', 'c'] tags: ['a', 'b', 'c']
},
created: function () {
this.$watch('tags', function () {
triggeredChange++
})
},
computed: {
concat: function () {
return this.tags.join(',')
}
} }
}) })
assert.strictEqual(v.concat, 'a,b,c')
assert.strictEqual(v.$el.textContent, 'abc') assert.strictEqual(v.$el.textContent, 'abc')
v.$.tags[0].$value = 'd' v.$.tags[0].$value = 'd'
assert.strictEqual(v.tags[0], 'd') assert.strictEqual(v.tags[0], 'd')
nextTick(function () {
assert.strictEqual(triggeredChange, 1)
assert.strictEqual(v.concat, 'd,b,c')
done()
})
}) })
it('should diff and reuse existing VMs when reseting arrays', function (done) { it('should diff and reuse existing VMs when reseting arrays', function (done) {