Răsfoiți Sursa

bindings that are not found are now created on current compiler instead of root

Evan You 12 ani în urmă
părinte
comite
1fb885b9fa
4 a modificat fișierele cu 49 adăugiri și 33 ștergeri
  1. 9 7
      examples/todomvc/js/app.js
  2. 17 13
      src/compiler.js
  3. 16 10
      src/exp-parser.js
  4. 7 3
      test/unit/specs/exp-parser.js

+ 9 - 7
examples/todomvc/js/app.js

@@ -1,3 +1,5 @@
+'use strict'
+
 var app = new Vue({
 
     // the root element that will be compiled
@@ -14,9 +16,10 @@ var app = new Vue({
         }
     },
 
-    // the `created` lifecycle hook.
-    // it will be called when the ViewModel instance is created.
+    // the `created` lifecycle hook, which will be called
+    // when the ViewModel instance is created but not yet compiled.
     created: function () {
+        // setup filters
         this.filters = {
             all: function (todo) { todo.completed; return true },
             active: function (todo) { return !todo.completed },
@@ -26,17 +29,16 @@ var app = new Vue({
         window.addEventListener('hashchange', function () {
             app.updateFilter()
         })
-        this.remaining = this.todos.filter(function (todo) {
-            return !todo.completed
-        }).length
+        // initialize some state
+        this.newTodo = ''
+        this.editedTodo = null
+        this.remaining = this.todos.filter(this.filters.active).length
     },
 
     // data
     data: {
-
         // fetch the saved todos from localStorage
         todos: todoStorage.fetch(),
-
         // a computed property with custom getter/setter
         allDone: {
             $get: function () {

+ 17 - 13
src/compiler.js

@@ -412,20 +412,24 @@ CompilerProto.bindDirective = function (directive) {
     if (directive.isExp) {
         // expression bindings are always created on current compiler
         binding = compiler.createBinding(key, true, directive.isFn)
-    } else if (
-        hasOwn.call(compiler.data, baseKey) ||
-        hasOwn.call(compiler.vm, baseKey)
-    ) {
-        // If the directive's compiler's VM has the base key,
-        // it belongs here. Create the binding if it's not created already.
-        binding = hasOwn.call(compiler.bindings, key)
-            ? compiler.bindings[key]
-            : compiler.createBinding(key)
     } else {
-        // due to prototypal inheritance of bindings, if a key doesn't exist
-        // on the bindings object, then it doesn't exist in the whole
-        // prototype chain. In this case we create the new binding at the root level.
-        binding = compiler.bindings[key] || compiler.rootCompiler.createBinding(key)
+        // recursively locate where to place the binding
+        while (compiler) {
+            if (
+                hasOwn.call(compiler.data, baseKey) ||
+                hasOwn.call(compiler.vm, baseKey)
+            ) {
+                // If a compiler has the base key, the directive should
+                // belong to it. Create the binding if it's not created already.
+                binding = hasOwn.call(compiler.bindings, key)
+                    ? compiler.bindings[key]
+                    : compiler.createBinding(key)
+                break
+            } else {
+                compiler = compiler.parentCompiler
+            }
+        }
+        if (!binding) binding = this.createBinding(key)
     }
 
     binding.instances.push(directive)

+ 16 - 10
src/exp-parser.js

@@ -53,10 +53,12 @@ function getVariables (code) {
  *  final resolved vm.
  */
 function getRel (path, compiler) {
-    var rel = '',
-        vm  = compiler.vm,
-        dot = path.indexOf('.'),
-        key = dot > -1
+    var rel  = '',
+        has  = false,
+        nest = 0,
+        vm   = compiler.vm,
+        dot  = path.indexOf('.'),
+        key  = dot > -1
             ? path.slice(0, dot)
             : path
     while (true) {
@@ -64,21 +66,25 @@ function getRel (path, compiler) {
             hasOwn.call(vm.$data, key) ||
             hasOwn.call(vm, key)
         ) {
+            has = true
             break
         } else {
             if (vm.$parent) {
                 vm = vm.$parent
-                rel += '$parent.'
+                nest++
             } else {
                 break
             }
         }
     }
-    compiler = vm.$compiler
-    if (
-        !hasOwn.call(compiler.bindings, path) &&
-        path.charAt(0) !== '$'
-    ) {
+    if (has) {
+        while (nest--) {
+            rel += '$parent.'
+        }
+        if (!hasOwn.call(vm.$compiler.bindings, path) && path.charAt(0) !== '$') {
+            vm.$compiler.createBinding(path)
+        }
+    } else {
         compiler.createBinding(path)
     }
     return rel

+ 7 - 3
test/unit/specs/exp-parser.js

@@ -75,15 +75,18 @@ describe('UNIT: Expression Parser', function () {
     function describeCase (testCase) {
         describe(testCase.exp, function () {
 
+            function createBinding (path) {
+                caughtMissingPaths.push(path)
+            }
+
             var caughtMissingPaths = [],
                 compilerMock = {
+                    createBinding: createBinding,
                     vm:{
                         $data: {},
                         $compiler:{
                             bindings:{},
-                            createBinding: function (path) {
-                                caughtMissingPaths.push(path)
-                            }
+                            createBinding: createBinding
                         }
                     }
                 },
@@ -118,6 +121,7 @@ describe('UNIT: Expression Parser', function () {
                 warned = true
             }
             ExpParser.parse('a + "fsef', {
+                createBinding: function () {},
                 vm: {
                     $compiler: {
                         bindings: {},