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

adjust context detection, ensure proper context in manual render functions

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

+ 1 - 1
src/compiler/codegen/index.js

@@ -110,7 +110,7 @@ function genChildren (el, asThunk) {
   }
   const code = '[' + el.children.map(genNode).join(',') + ']'
   return asThunk
-    ? `_renderWithContext(function(){return ${code}})`
+    ? `function(){return ${code}}`
     : code
 }
 

+ 0 - 2
src/runtime/global-api/index.js

@@ -1,6 +1,5 @@
 import config from '../config'
 import * as util from '../util/index'
-import { createElement } from '../vdom/index'
 import { initUse } from './use'
 import { initMixin } from './mixin'
 import { initExtend } from './extend'
@@ -13,7 +12,6 @@ export function initGlobalAPI (Vue) {
   Vue.set = set
   Vue.delete = del
   Vue.nextTick = nextTick
-  Vue.h = Vue.createElement = createElement
 
   Vue.options = {
     directives: Object.create(null),

+ 6 - 18
src/runtime/instance/render.js

@@ -6,6 +6,7 @@ import {
   flatten
 } from '../vdom/index'
 import {
+  bind,
   extend,
   resolveAsset,
   isArray,
@@ -14,14 +15,16 @@ import {
 } from '../util/index'
 
 export const renderState = {
-  activeInstance: null,
-  context: null
+  activeInstance: null
 }
 
 export function initRender (vm) {
   vm._vnode = null
   vm._mounted = false
   vm.$slots = {}
+  // bind the public createElement fn to this instance
+  // so that we get proper render context inside it.
+  vm.$createElement = bind(vm.__h__, vm)
   if (vm.$options.el) {
     vm.$mount(vm.$options.el)
   }
@@ -79,21 +82,6 @@ export function renderMixin (Vue) {
     }
   }
 
-  /**
-   * Call a render function with this instance as the context.
-   * This is used to wrap all children thunks in codegen.
-   */
-
-  Vue.prototype._renderWithContext = function (fn) {
-    return () => {
-      const prev = renderState.context
-      renderState.context = this
-      const children = flatten(fn())
-      renderState.context = prev
-      return children
-    }
-  }
-
   Vue.prototype._render = function () {
     const prev = renderState.activeInstance
     renderState.activeInstance = this
@@ -121,7 +109,7 @@ export function renderMixin (Vue) {
 
 function resolveSlots (vm, children) {
   if (children) {
-    children = children()
+    children = flatten(isArray(children) ? children : children())
     const slots = { default: children }
     let i = children.length
     let name, child

+ 9 - 0
src/runtime/vdom/component.js

@@ -1,10 +1,19 @@
 import Vue from '../instance/index'
 import { callHook } from '../instance/lifecycle'
+import { warn } from '../util/index'
 
 export default function Component (Ctor, data, parent, children, context) {
   if (typeof Ctor === 'object') {
     Ctor = Vue.extend(Ctor)
   }
+  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.'
+    )
+  }
   // return a placeholder vnode
   return {
     tag: 'component',

+ 1 - 1
src/runtime/vdom/create-element.js

@@ -11,8 +11,8 @@ import {
 
 export default function createElement (tag, data, children) {
   data = data || {}
+  const context = this
   const parent = renderState.activeInstance
-  const context = renderState.context || parent
   if (typeof tag === 'string') {
     let Ctor
     if (isReservedTag(tag)) {