Răsfoiți Sursa

thunkify children

Evan You 10 ani în urmă
părinte
comite
1df748d57d

+ 10 - 3
src/compiler/codegen/index.js

@@ -1,5 +1,6 @@
 import { genHandlers } from './events'
 import { genDirectives } from './directives/index'
+import { isReservedTag } from '../../runtime/util/dom'
 
 export function generate (ast) {
   const code = ast ? genElement(ast) : '__h__("div")'
@@ -18,7 +19,10 @@ function genElement (el) {
   } else if (el.tag === 'slot') {
     return genSlot(el)
   } else {
-    return `__h__('${el.tag}', ${genData(el)}, ${genChildren(el)})`
+    // if the element is potentially a component,
+    // wrap its children as a thunk.
+    const children = genChildren(el, !isReservedTag(el.tag))
+    return `__h__('${el.tag}', ${genData(el)}, ${children})`
   }
 }
 
@@ -92,11 +96,14 @@ function genData (el) {
   return data.replace(/,$/, '') + '}'
 }
 
-function genChildren (el) {
+function genChildren (el, asThunk) {
   if (!el.children.length) {
     return 'undefined'
   }
-  return '[' + el.children.map(genNode).join(',') + ']'
+  const code = '[' + el.children.map(genNode).join(',') + ']'
+  return asThunk
+    ? `function(){return ${code}}`
+    : code
 }
 
 function genNode (node) {

+ 11 - 4
src/runtime/instance/render.js

@@ -85,9 +85,16 @@ export function renderMixin (Vue) {
 
   Vue.prototype.$mount = function (el) {
     callHook(this, 'beforeMount')
-    this.$el = el && query(el)
-    if (this.$el) {
-      this.$el.innerHTML = ''
+    el = this.$el = el && query(el)
+    if (el) {
+      // clean element
+      el.innerHTML = ''
+      if (el.hasAttributes()) {
+        const attrs = el.attributes
+        for (let i = 0, l = attrs.length; i < l; i++) {
+          el.removeAttribute(attrs[i].name)
+        }
+      }
     }
     this._watcher = new Watcher(this, this._render, this._update)
     this._update(this._watcher.value)
@@ -103,7 +110,7 @@ export function renderMixin (Vue) {
 
 function resolveSlots (vm, children) {
   if (children) {
-    children = children.slice()
+    children = children().slice()
     const slots = { default: children }
     let i = children.length
     let name, child

+ 3 - 4
src/runtime/vdom/create-element.js

@@ -10,12 +10,11 @@ import {
 } from '../util/index'
 
 export default function createElement (tag, data, children) {
-  children = flatten(children)
   const parent = renderState.activeInstance
   if (typeof tag === 'string') {
     let Ctor
     if (isReservedTag(tag)) {
-      return VNode(tag, data, children)
+      return VNode(tag, data, flatten(children))
     } else if ((Ctor = resolveAsset(parent.$options, 'components', tag))) {
       return Component(Ctor, data, parent, children)
     } else {
@@ -26,14 +25,14 @@ export default function createElement (tag, data, children) {
           'make sure to provide the "name" option.'
         )
       }
-      return VNode(tag, data, children)
+      return VNode(tag, data, flatten(children()))
     }
   } else {
     return Component(tag, data, parent, children)
   }
 }
 
-function flatten (children) {
+export function flatten (children) {
   if (isArray(children)) {
     let res = []
     for (let i = 0, l = children.length; i < l; i++) {