UNPKG

vue

Version:

Reactive, component-oriented view layer for modern web interfaces.

125 lines (114 loc) 4.05 kB
/* @flow */ import { warn, nextTick, toNumber, toString, looseEqual, emptyObject, handleError, looseIndexOf } from '../util/index' import VNode, { cloneVNodes, createTextVNode, createEmptyVNode } from '../vdom/vnode' import { createElement } from '../vdom/create-element' import { renderList } from './render-helpers/render-list' import { renderSlot } from './render-helpers/render-slot' import { resolveFilter } from './render-helpers/resolve-filter' import { checkKeyCodes } from './render-helpers/check-keycodes' import { bindObjectProps } from './render-helpers/bind-object-props' import { renderStatic, markOnce } from './render-helpers/render-static' import { resolveSlots, resolveScopedSlots } from './render-helpers/resolve-slots' export function initRender (vm: Component) { vm._vnode = null // the root of the child tree vm._staticTrees = null const parentVnode = vm.$vnode = vm.$options._parentVnode // the placeholder node in parent tree const renderContext = parentVnode && parentVnode.context vm.$slots = resolveSlots(vm.$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) } export function renderMixin (Vue: Class<Component>) { Vue.prototype.$nextTick = function (fn: Function) { return nextTick(fn, this) } Vue.prototype._render = function (): VNode { const vm: Component = this const { render, staticRenderFns, _parentVnode } = vm.$options if (vm._isMounted) { // clone slot nodes on re-renders for (const key in vm.$slots) { vm.$slots[key] = cloneVNodes(vm.$slots[key]) } } vm.$scopedSlots = (_parentVnode && _parentVnode.data.scopedSlots) || emptyObject if (staticRenderFns && !vm._staticTrees) { vm._staticTrees = [] } // 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 function`) // return error render result, // or previous vnode to prevent render error causing blank component /* istanbul ignore else */ if (process.env.NODE_ENV !== 'production') { vnode = vm.$options.renderError ? vm.$options.renderError.call(vm._renderProxy, vm.$createElement, e) : 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 } // internal render helpers. // these are exposed on the instance prototype to reduce generated render // code size. Vue.prototype._o = markOnce Vue.prototype._n = toNumber Vue.prototype._s = toString Vue.prototype._l = renderList Vue.prototype._t = renderSlot Vue.prototype._q = looseEqual Vue.prototype._i = looseIndexOf Vue.prototype._m = renderStatic Vue.prototype._f = resolveFilter Vue.prototype._k = checkKeyCodes Vue.prototype._b = bindObjectProps Vue.prototype._v = createTextVNode Vue.prototype._e = createEmptyVNode Vue.prototype._u = resolveScopedSlots }