vue2 模版编译render转虚拟节点的初步分析

95 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第27天,点击查看活动详情

我们在上一篇文章成功把AST树用,拼接字符串的方式表现了出来 请看文章vue2的模版编译 对children的字符串拼接 下面我们就需要写render函数了,可以简单看下代码

function compileToRenderFunction(html) {
   console.log(html)
   const ast = paresHtmlToAst(html) // 这个函数是转AST 用的
   console.log(ast)
   // 返回一个code
   let code = generate(ast) // 这个是对AST树的解析
   let render = new Function(` // 这个就是render函数
      with(this) { return ${code} } // 用with 可以更加方便的替换调变量
   `)
   console.log(render)

}

来看一下为啥用with,with可以固定作用域,在使用对象属性时,可以不写最前的对象名称

let obj = { a: 1,b:2 }

with(obj) {
   console.log(a)
   console.log(b)      
}
// 大家可以看下打印出来的数据 

vue3.png 咱们可以看下我们打印出来的render是什么样子

vue4.png render函数我们打印出来了,下面要做的就是把render函数转化为虚拟节点了,转化虚拟节点其实一个挂载的过程, 这里我们就需要一个生命周期函数的一个混入方法了 可以看下index.js里的代码

import { initMixin } from './init.js'
import { lifecycleMixin } from './lifecycle.js'

class Vue{
  constructor(options) {
     this._init(options)  
  }
}
initMixin(Vue) // 初始化混入把模版变成拼接字符串
lifecycleMixin(Vue) // 混入的生命周期方法,update方法把拼接字符串代码转化为render可执行代码,然后变为虚咱们可以看下 lifecycleMixin.js里的方法
拟节点,然后对比,做出差异化处理,给真实dom打补丁

export default Vue

咱们可以看下 lifecycleMixin.js里的方法

function mountComponent(vm) { // 其实是一个生命周期函数
   // 执行就是lifecycleMixin函数混入的 update更新方法
   // 重点描述一下 _render()这个函数和 render是不一眼
   // _render()函数执行完是虚拟节点
   // render() 返回的是function函数
   vm._update(vm._render()) // 需要传入虚拟节点 render函数执行 变成虚拟节点
}

function lifecycleMixin(Vue) {
    Vue.prototype._update = function (vnode) { // 给vue实例添加了update方法,具体逻辑也是这里在做
       const vm = this;
    }
}
export {
    mountComponent,
    lifecycleMixin
}