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

Fix inline partial parentNode problem

Directives inside inline partials would get the fragment as the parentNode
if they are compiled before the partial is appended to the correct parentNode.
Therefore keep the reference of the fragment's childNodes, append it,
then compile afterwards fixes the problem.
Evan You 12 лет назад
Родитель
Сommit
5f21eed2c9
3 измененных файлов с 42 добавлено и 9 удалено
  1. 22 5
      src/compiler.js
  2. 18 3
      test/functional/fixtures/template.html
  3. 2 1
      test/functional/specs/template.js

+ 22 - 5
src/compiler.js

@@ -343,20 +343,24 @@ CompilerProto.compileNode = function (node) {
  *  Compile a text node
  */
 CompilerProto.compileTextNode = function (node) {
+
     var tokens = TextParser.parse(node.nodeValue)
     if (!tokens) return
-    var el, token, directive
+    var el, token, directive, partial, partialId, partialNodes
+
     for (var i = 0, l = tokens.length; i < l; i++) {
         token = tokens[i]
         if (token.key) { // a binding
             if (token.key.charAt(0) === '>') { // a partial
-                var partialId = token.key.slice(1).trim(),
-                    partial = this.getOption('partials', partialId)
+                partialId = token.key.slice(1).trim()
+                partial = this.getOption('partials', partialId)
                 if (partial) {
                     el = partial.cloneNode(true)
-                    this.compileNode(el)
+                    // save an Array reference of the partial's nodes
+                    // so we can compile them AFTER appending the fragment
+                    partialNodes = slice.call(el.childNodes)
                 }
-            } else { // a binding
+            } else { // a real binding
                 el = document.createTextNode('')
                 directive = Directive.parse('text', token.key, this, el)
                 if (directive) {
@@ -366,7 +370,20 @@ CompilerProto.compileTextNode = function (node) {
         } else { // a plain string
             el = document.createTextNode(token)
         }
+
+        // insert node
         node.parentNode.insertBefore(el, node)
+
+        // compile partial after appending, because its children's parentNode
+        // will change from the fragment to the correct parentNode.
+        // This could affect directives that need access to its element's parentNode.
+        if (partialNodes) {
+            for (var j = 0, k = partialNodes.length; j < k; j++) {
+                this.compile(partialNodes[j])
+            }
+            partialNodes = null
+        }
+
     }
     node.parentNode.removeChild(node)
 }

+ 18 - 3
test/functional/fixtures/template.html

@@ -8,15 +8,20 @@
     <body>
 
         <div id="usa" v-partial="global"></div>
-        <div id="japan" v-partial="local"></div>
+        <div id="japan">{{> local}}</div>
+        <div id="repeat">{{> repeat}}</div>
 
         <script type="text/v-template" id="test">
             <p>{{hi}}!</p>
         </script>
 
+        <script type="text/v-template" id="repeat-template">
+            <p v-repeat="items">{{title}}</p>
+        </script>
+
         <script>
 
-            Vue.config({debug:true})
+           // Vue.config({debug:true})
 
             // direct usage
             var china  = new Vue({
@@ -48,10 +53,20 @@
             var japan = new Vue({
                 el: '#japan',
                 partials: {
-                    local: document.querySelector('#test').innerHTML
+                    local: '#test'
                 }
             })
             japan.hi = 'こんにちは'
+
+            var repeat = new Vue({
+                el: '#repeat',
+                partials: {
+                    repeat: '#repeat-template'
+                },
+                data: {
+                    items: [{ title: 'Repeat' }]
+                }
+            })
         </script>
     </body>
 </html>

+ 2 - 1
test/functional/specs/template.js

@@ -1,4 +1,4 @@
-casper.test.begin('Template', 4, function (test) {
+casper.test.begin('Templates and Partials', 5, function (test) {
     
     casper
     .start('./fixtures/template.html')
@@ -7,6 +7,7 @@ casper.test.begin('Template', 4, function (test) {
         test.assertSelectorHasText('#japan', 'こんにちは', 'local partial')
         test.assertSelectorHasText('#china', '你好', 'direct option')
         test.assertSelectorHasText('#hawaii', 'Aloha', 'extend option')
+        test.assertSelectorHasText('#repeat', 'Repeat', 'inline partial with repeat')
     })
     .run(function () {
         test.done()