Parcourir la source

make primitive arrays work with computed property

Evan You il y a 12 ans
Parent
commit
8d65a078f3
3 fichiers modifiés avec 39 ajouts et 18 suppressions
  1. 15 14
      src/directives/repeat.js
  2. 6 3
      src/observer.js
  3. 18 1
      test/unit/specs/directives.js

+ 15 - 14
src/directives/repeat.js

@@ -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,
-            vms = this.vms,
-            col = this.collection,
+        var self = this,
+            ctn = self.container,
+            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) {
-                    if (key === '$value') {
-                        col[item.$index] = val
-                    }
+                item.$compiler.observer.on('change:$value', function (val) {
+                    self.lock = true
+                    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)

+ 6 - 3
src/observer.js

@@ -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,
-            args: args,
-            result: result
+            method   : method,
+            args     : args,
+            result   : result,
+            inserted : inserted,
+            removed  : removed
         })
         })
 
 
         return result
         return result

+ 18 - 1
test/unit/specs/directives.js

@@ -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) {