Vue官方文档梳理-DOM

原创
前端路迹
2018-3-14 16:18
编辑于 2022-6-17 15:25

el

!>如果 render 函数和 template 属性都不存在,挂载 DOM 元素的 HTML 会被提取出来用作模板,此时,必须使用 Runtime + Compiler 构建的 Vue 库。

Vue$3.prototype.$mount = function(el, hydrating) {

    el = el && query(el);

    // 不能挂载到 body 和 html 上
    if (el === document.body || el === document.documentElement) {
        // 发出警告
        return this
    }

    var options = this.$options;

    // 如果没有配置 render 
    if (!options.render) {
        var template = options.template;
        if (template) {
            // ...
        } else if (el) {
            // 配置了el,没有配置 render,那么将 el 的 html 作为 template
            template = getOuterHTML(el);
        }
        if (template) {
            // 调用 compileToFunctions 将 template 编译成 render 函数
            // ...
        }
    }
    return mount.call(this, el, hydrating)
}

template

!>如果 Vue 选项中包含 render 函数,template 选项将被忽略。

上面的源码中,如果配置了 render,则不会对 template 配置项编译。因此优先级如下:

render > template > el

!>但是如果你在 vue 文件中即使用了 <template>,又配置了 render,<template> 的内容会被编译成 render 函数,渲染的时候使用的是编译生成的 render,而不是配置的。

render

官网指出:组件树中的所有 VNodes 必须是唯一的。这意味着,下面的 render function 是无效的:

render: function (createElement) {
  var myParagraphVNode = createElement('p', 'hi')
  return createElement('div', [
    // 错误-重复的 VNodes
    myParagraphVNode, myParagraphVNode
  ])
}

即使在开发版本下运行,上面的代码也没有报错。不知道这里的影响点具体是什么。

##renderError

在 2.2.0 版本之前的版本只会调用全局配置的 config.errorHandler,比如 2.1.2 的源码如下。

try {
    vnode = render.call(vm._renderProxy, vm.$createElement);
} catch (e) {
    if (config.errorHandler) {
        config.errorHandler.call(null, e, vm);
    } else {
        // ...
    }
    vnode = vm._vnode;
}

在 2.2.0 版本之后,不仅会调用全局配置的 errorHandler,而且还会调用配置的 renderError。

try {
    vnode = render.call(vm._renderProxy, vm.$createElement);
} catch (e) {
    handleError(e, vm, "render function"); // handleError 里面调用了 config.errorHandler
    // return error render result,
    // or previous vnode to prevent render error causing blank component
    {
        vnode = vm.$options.renderError ? vm.$options.renderError.call(vm._renderProxy, vm.$createElement, e) : vm._vnode;
    }
}
转载请注明出处。本文地址: https://www.qinshenxue.com/article/20170918102007.html
关注我的公众号