Bootstrap

【Vue2.x 源码学习】第十七篇 - 生成 render 函数 - 函数生成

一,前言

上篇,主要介绍了生成 render 函数 - 代码拼接,主要涉及一下几个点:

  • render 函数的代码拼接:generate(ast)

  • 处理属性:genProps(ast.attrs)

  • 处理属性中的样式

  • 递归深层处理儿子:genChildren

本篇,生成 render 函数 - 函数生成

二,包装 code 生成 render 函数

1,render 函数对比

对比 vue2.0 模板生成的 render 函数:

上篇,完成了 return 内部的代码拼接工作,即 render 函数中 with 内部的代码拼接已经完成

距离真正的 render 函数,还差两步:

1,包装 with

2,包装成为 Function

2,包装 with 并生成 render 函数

export function compileToFunction(template) {
  console.log("***** 进入 compileToFunction:将 template 编译为 render 函数 *****")
  // 1,将模板变成 AST 语法树
  let ast = parserHTML(template);
  // 2,使用 AST 生成 render 函数
  let code = generate(ast);
  let render = new Function(`with(this){return ${code}}`);
  console.log("包装 with 生成 render 函数:"+ render.toString())
  
  return render
}

将生成的 render 函数保存到 options 选项:

Vue.prototype.$mount = function (el) {
    const vm = this;
    const opts = vm.$options;
    el = document.querySelector(el);
    vm.$el = el;
    if (!opts.render) {
      let template = opts.template;
      if (!template) {
        template = el.outerHTML;
      }

      let render = compileToFunction(template);
      opts.render = render;	// 保存生成的 render 函数
      console.log("打印 compileToFunction 返回的 render = " + JSON.stringify(render))
    }
  
  	// 后续工作:
  	// 1)根据 render 函数,生成虚拟 dom...
  	// 2)虚拟 dom + 真实数据 => 生成真实 dom...
  }

测试 render 函数生成:

3,生成 render 函数的大致流程:

从 html模板到生成 render 函数的大致流程:

  • html模板编译称为 ast 语法树;

  • ast 语法树生成并拼接 code

  • 使用 with 对生成的 code 进行一次包装

  • 将包装后的完整 code 字符串,通过 new Function 输出为 render 函数

TODO: 详细说明模板引擎的实现原理:new Function + with

三,结尾

又成功水了一篇,还剩 4 篇

本篇,生成 render 函数 - 函数生成,主要做了以下两件事

  • 使用 with 对生成的 code 进行一次包装

  • 将包装后的完整 code 字符串,通过 new Function 输出为 render 函数

下一篇,根据 render 函数,生成虚拟节点