소스 검색

support paths for track-by (close #2632)

Evan You 10 년 전
부모
커밋
6ac14be0fa
2개의 변경된 파일48개의 추가작업 그리고 3개의 파일을 삭제
  1. 4 3
      src/directives/public/for.js
  2. 44 0
      test/unit/specs/directives/public/for/for_spec.js

+ 4 - 3
src/directives/public/for.js

@@ -1,6 +1,7 @@
 import FragmentFactory from '../../fragment/factory'
 import { FOR } from '../priorities'
 import { withoutConversion } from '../../observer/index'
+import { getPath } from '../../parsers/path'
 import {
   isObject,
   warn,
@@ -405,7 +406,7 @@ const vFor = {
       id = trackByKey
         ? trackByKey === '$index'
           ? index
-          : value[trackByKey]
+          : getPath(value, trackByKey)
         : (key || value)
       if (!cache[id]) {
         cache[id] = frag
@@ -446,7 +447,7 @@ const vFor = {
       var id = trackByKey
         ? trackByKey === '$index'
           ? index
-          : value[trackByKey]
+          : getPath(value, trackByKey)
         : (key || value)
       frag = this.cache[id]
     } else {
@@ -478,7 +479,7 @@ const vFor = {
       var id = trackByKey
         ? trackByKey === '$index'
           ? index
-          : value[trackByKey]
+          : getPath(value, trackByKey)
         : (key || value)
       this.cache[id] = null
     } else {

+ 44 - 0
test/unit/specs/directives/public/for/for_spec.js

@@ -528,6 +528,50 @@ describe('v-for', function () {
     }
   })
 
+  it('track by nested id path', function (done) {
+    var vm = new Vue({
+      el: el,
+      template: '<test v-for="item in list" :item="item" track-by="nested.id"></test>',
+      data: {
+        list: [
+          { nested: { id: 1 }, msg: 'foo' },
+          { nested: { id: 2 }, msg: 'bar' },
+          { nested: { id: 3 }, msg: 'baz' }
+        ]
+      },
+      components: {
+        test: {
+          props: ['item'],
+          template: '{{item.msg}}'
+        }
+      }
+    })
+    assertMarkup()
+    var oldVms = vm.$children.slice()
+    // swap the data with different objects, but with
+    // the same ID!
+    vm.list = [
+      { nested: { id: 1 }, msg: 'qux' },
+      { nested: { id: 2 }, msg: 'quux' }
+    ]
+    _.nextTick(function () {
+      assertMarkup()
+      // should reuse old vms!
+      var i = 2
+      while (i--) {
+        expect(vm.$children[i]).toBe(oldVms[i])
+      }
+      done()
+    })
+
+    function assertMarkup () {
+      var markup = vm.list.map(function (item) {
+        return '<test>' + item.msg + '</test>'
+      }).join('')
+      expect(el.innerHTML).toBe(markup)
+    }
+  })
+
   it('track by $index', function (done) {
     var vm = new Vue({
       el: el,