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.
This commit is contained in:
Evan You 2014-01-16 17:04:49 -05:00
parent b63b551439
commit 5f21eed2c9
3 changed files with 42 additions and 9 deletions

View File

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

View File

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

View File

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