Render method

Vue and _render method is the instance of a private method, it is used to render a virtual Node, it defined in SRC/core/instance/render. The js file:

Vue.prototype._render = function () :VNode {
    const vm: Component = this
    const { render, _parentVnode } = vm.$options

    if (_parentVnode) {
      vm.$scopedSlots = normalizeScopedSlots(
        _parentVnode.data.scopedSlots,
        vm.$slots,
        vm.$scopedSlots
      )
    }

    // 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 {
      // There's no need to maintain a stack because all render fns are called
      // separately from one another. Nested component's render fns are called
      // when parent component is patched.
      currentRenderingInstance = vm
      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' && 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
      }
    } finally {
      currentRenderingInstance = null
    }
    // if the returned array contains only a single node, allow it
    if (Array.isArray(vnode) && vnode.length === 1) {
      vnode = vnode[0]}// return empty vnode in case the render function errored out
    if(! (vnodeinstanceof 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
  }
Copy the code

The most critical part of this code is the call to the Render method. We usually write the render method in the development of the scene is less, usually template template, in the previous Mounted method, template will be compiled into the render method. It’s a very complicated process and we’ll see that later.

CreateElement, the first argument to the render function, is described in the official documentation as follows:

<div id="app">
  {{ message }}
</div>
Copy the code

Equivalent to writing the render function:

render: function (createElement) {
  return createElement('div', {
     attrs: {
        id: 'app'}},this.message)
}
Copy the code

Let’s look at the render method call in the _render function:

vnode = render.call(vm._renderProxy, vm.$createElement)
Copy the code

$createElement vm.$createElement vm.$createElement vm.

export function initRender (vm: Component) {
  // ...
  // 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)}Copy the code

In fact, the vm.$createElement method is defined when the initRender method is executed. There is also a vm._c method that is used by the template-compiled render function, while the vm. Both methods have the same parameters and both call the createElement method.

conclusion

Vm. _render is ultimately a vNode virtual Node returned by executing the createElement method. The next article will briefly cover the Virtual DOM in VUE

Vue2 source code analysis (3)

Vue2 source code analysis (2)

Vue2 source code analysis (a)