diff options
Diffstat (limited to 'node_modules/vue/src/core/instance/render.js')
| -rw-r--r-- | node_modules/vue/src/core/instance/render.js | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/node_modules/vue/src/core/instance/render.js b/node_modules/vue/src/core/instance/render.js new file mode 100644 index 00000000..70fb2c0e --- /dev/null +++ b/node_modules/vue/src/core/instance/render.js @@ -0,0 +1,119 @@ +/* @flow */ + +import { + warn, + nextTick, + emptyObject, + handleError, + defineReactive +} from '../util/index' + +import { createElement } from '../vdom/create-element' +import { installRenderHelpers } from './render-helpers/index' +import { resolveSlots } from './render-helpers/resolve-slots' +import VNode, { createEmptyVNode } from '../vdom/vnode' + +import { isUpdatingChildComponent } from './lifecycle' + +export function initRender (vm: Component) { + vm._vnode = null // the root of the child tree + vm._staticTrees = null // v-once cached trees + const options = vm.$options + const parentVnode = vm.$vnode = options._parentVnode // the placeholder node in parent tree + const renderContext = parentVnode && parentVnode.context + vm.$slots = resolveSlots(options._renderChildren, renderContext) + vm.$scopedSlots = emptyObject + // bind the createElement fn to this instance + // so that we get proper render context inside it. + // args order: tag, data, children, normalizationType, alwaysNormalize + // internal version is used by render functions compiled from templates + vm._c = (a, b, c, d) => createElement(vm, a, b, c, d, false) + // normalization is always applied for the public version, used in + // user-written render functions. + vm.$createElement = (a, b, c, d) => createElement(vm, a, b, c, d, true) + + // $attrs & $listeners are exposed for easier HOC creation. + // they need to be reactive so that HOCs using them are always updated + const parentData = parentVnode && parentVnode.data + + /* istanbul ignore else */ + if (process.env.NODE_ENV !== 'production') { + defineReactive(vm, '$attrs', parentData && parentData.attrs || emptyObject, () => { + !isUpdatingChildComponent && warn(`$attrs is readonly.`, vm) + }, true) + defineReactive(vm, '$listeners', options._parentListeners || emptyObject, () => { + !isUpdatingChildComponent && warn(`$listeners is readonly.`, vm) + }, true) + } else { + defineReactive(vm, '$attrs', parentData && parentData.attrs || emptyObject, null, true) + defineReactive(vm, '$listeners', options._parentListeners || emptyObject, null, true) + } +} + +export function renderMixin (Vue: Class<Component>) { + // install runtime convenience helpers + installRenderHelpers(Vue.prototype) + + Vue.prototype.$nextTick = function (fn: Function) { + return nextTick(fn, this) + } + + Vue.prototype._render = function (): VNode { + const vm: Component = this + const { render, _parentVnode } = vm.$options + + // reset _rendered flag on slots for duplicate slot check + if (process.env.NODE_ENV !== 'production') { + for (const key in vm.$slots) { + // $flow-disable-line + vm.$slots[key]._rendered = false + } + } + + if (_parentVnode) { + vm.$scopedSlots = _parentVnode.data.scopedSlots || emptyObject + } + + // set parent vnode. this allows render functions to have access + // to the data on the placeholder node. + vm.$vnode = _parentVnode + // render self + let vnode + try { + vnode = render.call(vm._renderProxy, vm.$createElement) + } catch (e) { + handleError(e, vm, `render`) + // return error render result, + // or previous vnode to prevent render error causing blank component + /* istanbul ignore else */ + if (process.env.NODE_ENV !== 'production') { + if (vm.$options.renderError) { + try { + vnode = vm.$options.renderError.call(vm._renderProxy, vm.$createElement, e) + } catch (e) { + handleError(e, vm, `renderError`) + vnode = vm._vnode + } + } else { + vnode = vm._vnode + } + } else { + vnode = vm._vnode + } + } + // return empty vnode in case the render function errored out + if (!(vnode instanceof VNode)) { + if (process.env.NODE_ENV !== 'production' && Array.isArray(vnode)) { + warn( + 'Multiple root nodes returned from render function. Render function ' + + 'should return a single root node.', + vm + ) + } + vnode = createEmptyVNode() + } + // set parent + vnode.parent = _parentVnode + return vnode + } +} |
