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

simplify children render mechanism

Evan You 10 лет назад
Родитель
Сommit
2dc5b17828

+ 9 - 3
src/core/instance/render.js

@@ -1,11 +1,17 @@
 /* @flow */
 
-import { renderElement, renderSelf, renderText, renderStatic } from '../vdom/create-element'
 import { emptyVNode } from '../vdom/vnode'
 import { normalizeChildren } from '../vdom/helpers'
 import { bind, remove, isObject, renderString } from 'shared/util'
 import { resolveAsset, nextTick } from '../util/index'
 
+import {
+  renderElement,
+  renderElementWithChildren,
+  renderText,
+  renderStatic
+} from '../vdom/create-element'
+
 export const renderState: {
   activeInstance: Component | null
 } = {
@@ -60,8 +66,8 @@ export function renderMixin (Vue: Class<Component>) {
   }
 
   // shorthands used in render functions
-  Vue.prototype.__r__ = renderElement
-  Vue.prototype.__s__ = renderSelf
+  Vue.prototype.__r__ = renderElementWithChildren
+  Vue.prototype.__s__ = renderElement
   Vue.prototype.__t__ = renderText
   Vue.prototype.__m__ = renderStatic
 

+ 5 - 12
src/core/vdom/create-component.js

@@ -10,19 +10,10 @@ const hooksToMerge = Object.keys(hooks)
 
 export function createComponent (
   Ctor: Class<Component> | Function | Object | void,
-  data: VNodeData | void,
+  data?: VNodeData,
   parent: Component,
-  context: Component,
-  children: ?VNodeChildren
+  context: Component
 ): VNode | void {
-  if (process.env.NODE_ENV !== 'production' &&
-    children && typeof children !== 'function') {
-    warn(
-      'A component\'s children should be a function that returns the ' +
-      'children array. This allows the component to track the children ' +
-      'dependencies and optimizes re-rendering.'
-    )
-  }
   if (!Ctor) {
     return
   }
@@ -75,7 +66,9 @@ export function createComponent (
   const vnode = new VNode(
     `vue-component-${Ctor.cid}${name}`,
     data, undefined, undefined, undefined, undefined, context,
-    { Ctor, propsData, listeners, parent, children }
+    { Ctor, propsData, listeners, parent, children: undefined }
+    // children to be set later by renderElementWithChildren,
+    // but before the init hook
   )
   return vnode
 }

+ 21 - 34
src/core/vdom/create-element.js

@@ -7,27 +7,33 @@ import { normalizeChildren } from './helpers'
 import { renderState } from '../instance/render'
 import { warn, resolveAsset } from '../util/index'
 
-export function renderElement (
-  vnode?: VNode | ComponentDef,
-  children?: VNodeChildren
+export function renderElementWithChildren (
+  vnode: VNode | void,
+  children: VNodeChildren | void
 ): VNode | void {
-  if (vnode instanceof ComponentDef) {
-    return createComponent(
-      vnode.Ctor, vnode.data, vnode.parent,
-      vnode.context, children
-    )
-  }
-  if (vnode instanceof VNode) {
-    vnode.setChildren(normalizeChildren(children))
+  if (vnode) {
+    if (vnode.componentOptions) {
+      if (process.env.NODE_ENV !== 'production' &&
+        children && typeof children !== 'function') {
+        warn(
+          'A component\'s children should be a function that returns the ' +
+          'children array. This allows the component to track the children ' +
+          'dependencies and optimizes re-rendering.'
+        )
+      }
+      vnode.componentOptions.children = children
+    } else {
+      vnode.setChildren(normalizeChildren(children))
+    }
   }
   return vnode
 }
 
-export function renderSelf (
+export function renderElement (
   tag?: string | Class<Component> | Function | Object,
   data?: VNodeData,
   namespace?: string
-): VNode | ComponentDef | void {
+): VNode | void {
   const context: Component = this
   const parent: Component | null = renderState.activeInstance
   if (!parent) {
@@ -49,7 +55,7 @@ export function renderSelf (
         undefined, undefined, namespace, context
       )
     } else if ((Ctor = resolveAsset(context.$options, 'components', tag))) {
-      return new ComponentDef(Ctor, data, parent, context)
+      return createComponent(Ctor, data, parent, context)
     } else {
       if (process.env.NODE_ENV !== 'production') {
         if (!namespace && config.isUnknownElement(tag)) {
@@ -66,7 +72,7 @@ export function renderSelf (
       )
     }
   } else {
-    return new ComponentDef(tag, data, parent, context)
+    return createComponent(tag, data, parent, context)
   }
 }
 
@@ -77,22 +83,3 @@ export function renderText (str?: string): string {
 export function renderStatic (index?: number): Object | void {
   return this._staticTrees[index]
 }
-
-export class ComponentDef {
-  Ctor: Class<Component> | Function | Object | void;
-  data: VNodeData | void;
-  parent: Component;
-  context: Component;
-
-  constructor (
-    Ctor?: Class<Component> | Function | Object,
-    data?: VNodeData,
-    parent: Component,
-    context: Component
-  ) {
-    this.Ctor = Ctor
-    this.data = data
-    this.parent = parent
-    this.context = context
-  }
-}

+ 6 - 3
src/core/vdom/helpers.js

@@ -6,12 +6,15 @@ import VNode from './vnode'
 const whitespace = new VNode(undefined, undefined, undefined, ' ')
 
 export function normalizeChildren (children: any): Array<VNode> {
-  if (typeof children === 'string') {
-    return [new VNode(undefined, undefined, undefined, children)]
-  }
+  // invoke children thunks.
+  // components always receive their children as thunks so that they
+  // can perform the actual render inside their own dependency collection cycle.
   if (typeof children === 'function') {
     children = children()
   }
+  if (typeof children === 'string') {
+    return [new VNode(undefined, undefined, undefined, children)]
+  }
   if (Array.isArray(children)) {
     const res = []
     for (let i = 0, l = children.length; i < l; i++) {