vue源码 模板编译

  • 模板编译的次要目标是将模板(template)转换为渲染函数(render)

模板编译作用

  • Vue2.x应用VNode形容视图以及各种交互,用户本人编写VNode 比较复杂
  • 用户只须要编写相似 HTML的代码 - Vue.js模板,通过编译器将模板转换为返回 VNode 的 render函数
  • .vue文件会被webpack在构建的过程中转换成 render函数 (外部通过vue-loader)
  • 运行时版本,vuecli默认应用
  • 构建时版本,体积大,构建速度慢

查看模板编译后果

<div id="app">  <h1>Vue<span>模板编译</span></h1>  <p>{{msg}}</p>  <comp></comp></div>Vue.component("comp",{  template:'<div>I am Comp</div>'})const vm = new  Vue({  el:"#app",  data:{    msg:'Hello Compiler'  },  methods:{    handler(){      console.log('test')    }  }})console.log(vm.$options.render)

获取render输入后果

  • with作用是示意上面_的办法都是vue实例的办法

    (function anonymous() {with(this) {  return _c(    'div', // tag标签    {attrs:{"id":"app"}}, // data用于形容tag    [          // children形容tag子节点      _m(0),   // 模板中的动态内容,对应下面的h1标签      _v(" "), // 创立空白文本,两个标签之间的空白      _c('p',[_v(_s(msg))]), // 创立p标签对应的vnode,参数二是文本      _v(" "),      _c('comp')    ],    1 // children 拍平  )}})
  • _c() 定义在 src/core/instance/render.js (h函数,用于创立vnode)
  • _m() / _v() / _s() 定义在 src/core/instance/render-helpers/index.js

将html模板转化为render渲染函数

  • 标签内的内容,空格换行,render会原样输入
  • 去掉无异于的换行空格,可进步性能,减小内存占用
  • vue3 对应的 explorer对其做了优化,换行空格不会保留

模板编译入口

  • src/platforms/web/entry-runtime-with-compiler.js

    // 把template转化为render 函数const { render, staticRenderFns } = compileToFunctions(template, {outputSourceRange: process.env.NODE_ENV !== 'production',shouldDecodeNewlines,shouldDecodeNewlinesForHref,delimiters: options.delimiters,comments: options.comments}, this)
  • 此办法在 src/compiler/to-function.js中
  • 会执行 compileToFunctions 中的 compile(template,options) 开始编译
  • compile 定义在 createCompilerCreator 内 ,会合并配置选项,调用 baseCompile(template.trim(),finalOptions)
  • baseCompile 定义在 createCompiler中, 是转化的外围
  • 次要做了三件事

    • 把template 转化为 ast 语法树对象
    • 对 ast 对象进行 动态标记,patch 时不比照动态节点差别, 间接返回,提高效率
    • 把 ast 对象 转化 为 js对象,把 js 对象 通过 createFunction转化成匿名函数
    • 解构进去,挂到 vm 实例上,编译过程完结
  • ast语法树对象入口

此时为增加完动态标记的ast对象

此时为转化成的 js 对象,此时的 ast 中标记了 staticProcessed:true 示意以及解决完了

export const createCompiler = createCompilerCreator(function baseCompile (  template: string, // 模板  options: CompilerOptions // 合并之后的选项): CompiledResult {  // 把模板转换成 ast 形象语法树  // 形象语法树用于以树的模式,形容代码构造  const ast = parse(template.trim(), options)  if (options.optimize !== false) {    // 优化形象语法树    optimize(ast, options)  }  // 把优化后的 形象语法树 转化成 字符串模式的 js 代码  const code = generate(ast, options)  // 返回 createCompiler对象  return {    ast,    render: code.render, // 渲染函数    staticRenderFns: code.staticRenderFns // 动态渲染函数,生成动态 VNode 树  }})
  • 留神:Vue2缩小空白换行,占内存,编译速度慢

Vue 源码 组件化

  • 一个Vue 组件,就是一个领有预约义选项的 一个Vue 实例
  • 一个组件能够组成页面上一个性能齐备的区域,组件能够蕴含脚本、款式、模板
  • 组件如同积木块,领有组件如同在拼积木。每个组件外部 能够嵌套 颗粒度更小 的根本组件
  • 组件化能够让咱们把页面拆分成多个可重用的组件

回顾组件注册

  • 全局组件 源码src/core/global-api/index.js
  • 部分组件
  • 返回了基于 组件选项对象 生成的 vue构造函数

Vue.extend

  • 把参数转化为Vue构造函数的子类
  • 定义在 core/global-api/extend.js