Просмотр исходного кода

v-repeat object first pass, value -> $value

Evan You 12 лет назад
Родитель
Сommit
393a4e2cfa
4 измененных файлов с 54 добавлено и 12 удалено
  1. 3 4
      src/compiler.js
  2. 42 5
      src/directives/repeat.js
  3. 6 1
      src/observer.js
  4. 3 2
      test/functional/fixtures/repeated-primitive.html

+ 3 - 4
src/compiler.js

@@ -98,12 +98,11 @@ function Compiler (vm, options) {
     // observe the data
     compiler.observeData(data)
     
-    // for repeated items, create an index binding
-    // which should be inenumerable but configurable
+    // for repeated items, create index/key bindings
+    // because they are ienumerable
     if (compiler.repeat) {
-        //data.$index = compiler.repeatIndex
-        def(data, '$index', compiler.repeatIndex, false, true)
         compiler.createBinding('$index')
+        if (data.$key) compiler.createBinding('$key')
     }
 
     // now parse the DOM, during which we will create necessary bindings

+ 42 - 5
src/directives/repeat.js

@@ -2,6 +2,7 @@ var Observer   = require('../observer'),
     utils      = require('../utils'),
     config     = require('../config'),
     transition = require('../transition'),
+    def        = utils.defProtected,
     ViewModel // lazy def to avoid circular dependency
 
 /**
@@ -77,6 +78,35 @@ var mutationHandlers = {
     }
 }
 
+/**
+ *  Convert an Object to a v-repeat friendly Array
+ */
+function objectToArray (obj) {
+    var res = [], val, data
+    for (var key in obj) {
+        val = obj[key]
+        data = utils.typeOf(val) === 'Object'
+            ? val
+            : { $value: val }
+        def(data, '$key', key, false, true)
+        res.push(data)
+    }
+    return res
+}
+
+/**
+ *  Find an object or a wrapped data object
+ *  from an Array
+ */
+function indexOf (arr, obj) {
+    for (var i = 0, l = arr.length; i < l; i++) {
+        if (arr[i] === obj || (obj.$value && arr[i].$value === obj.$value)) {
+            return i
+        }
+    }
+    return -1
+}
+
 module.exports = {
 
     bind: function () {
@@ -119,6 +149,12 @@ module.exports = {
     },
 
     update: function (collection, init) {
+
+        if (utils.typeOf(collection) === 'Object') {
+            this.object = collection
+            collection = objectToArray(collection)
+            def(this.object, '$repeater', collection, false, true)
+        }
         
         if (collection === this.collection) return
 
@@ -204,9 +240,9 @@ module.exports = {
         if (data) {
 
             if (this.old) {
-                i = this.old.indexOf(data)
+                i = indexOf(this.old, data)
             }
-            
+
             if (i > -1) { // existing, reuse the old VM
 
                 item = this.oldVMs[i]
@@ -227,8 +263,10 @@ module.exports = {
                 // wrap primitive element in an object
                 if (utils.typeOf(data) !== 'Object') {
                     primitive = true
-                    data = { value: data }
+                    data = { $value: data }
                 }
+                // define index
+                def(data, '$index', index, false, true)
 
             }
 
@@ -250,7 +288,6 @@ module.exports = {
             data: data,
             compilerOptions: {
                 repeat: true,
-                repeatIndex: index,
                 parentCompiler: this.compiler,
                 delegator: ctn
             }
@@ -265,7 +302,7 @@ module.exports = {
             // for primitive values, listen for value change
             if (primitive) {
                 data.__observer__.on('set', function (key, val) {
-                    if (key === 'value') {
+                    if (key === '$value') {
                         col[item.$index] = val
                     }
                 })

+ 6 - 1
src/observer.js

@@ -131,7 +131,12 @@ function watchArray (arr) {
  */
 function convert (obj, key) {
     var keyPrefix = key.charAt(0)
-    if ((keyPrefix === '$' || keyPrefix === '_') && key !== '$index') {
+    if (
+        (keyPrefix === '$' || keyPrefix === '_') &&
+        key !== '$index' &&
+        key !== '$key' &&
+        key !== '$value'
+    ) {
         return
     }
     // emit set on bind

+ 3 - 2
test/functional/fixtures/repeated-primitive.html

@@ -1,11 +1,12 @@
 <div id="test">
-    <p v-repeat="numbers" v-on="click: value+=' modified'">{{value}}</p>
+    <p v-repeat="numbers" v-on="click: $value+=' modified'">{{$value}}</p>
 </div>
 
 <script src="../../../dist/vue.js"></script>
 <script>
+    Vue.config('debug', true)
     var numbers = [1, 2, 'text']
-    new Vue({
+    var test = new Vue({
         el: '#test',
         data: {
             numbers: numbers