Vue.js 模板编译 - 解析(parse)

「这是我参与2022首次更文挑战的第23天,活动详情查看:2022首次更文挑战

Vue.js 源码分析 - parse

parse 解析器将模板解析为抽象语树 AST,只有将模板解析成 AST 后,才能基于它做优化或者生成代码字符串。

模板编译的过程 baseCompile

在学习 parse 函数之前,我们需要先了解是如何调用这个函数,何时调用的

这就需要我们先了解 baseCompile 函数了,baseCompile 是模板编译的核心函数,他一共做了三个事情 路径: src\compiler\index.js

  1. 调用 parse:把模板转换成 ast 抽象语法树,然后优化抽象语法树
  2. 调用 generate: 把抽象语法树生成字符串形式的 js 代码
  3. 返回一个包含以下数据内容的对象 :
    • ast
    • render(渲染函数)(这里并不是render函数,而是一个字符串形式的数据,需要 toFunction 转换成函数形式)
    • staticRenderFns(静态渲染函数,生成静态)

parse 函数解析

  • src\compiler\index.js
    • 把模板转化成 ast抽象语法树
    • 抽象语法树,用来以树形的方式描述代码结构
    const ast = parse(template.trim(), options)
    复制代码
  • src\compiler\parser\index.js
    parse()
    复制代码

工具页面推荐

查看得到的 AST tree

结构化指令的处理

  • v-if 最终生成单元表达式
// src\compiler\parser\index.js
// structural directives
// 结构化的指令
// v-for
processFor(element)
processIf(element)
processOnce(element)

// src\compiler\codegen\index.js
export function genIf (
    el: any,
    state: CodegenState,
    altGen?: Function,
    altEmpty?: string
): string {
    el.ifProcessed = true // avoid recursion
    return genIfConditions(el.ifConditions.slice(), state, altGen, altEmpty)
}
// 最终调用 genIfConditions 生成三元表达式
复制代码
  • v-if 最终编译的结果
ƒ anonymous(
) {
    with(this){
        return _c('div',{attrs:{"id":"app"}},[
            _m(0),
            _v(" "),
            (msg)?_c('p',[_v(_s(msg))]):_e(),_v(" "),
            _c('comp',{on:{"myclick":onMyClick}})
        ],1)
    }
}
复制代码

v-if/v-for 结构化指令只能在编译阶段处理,如果我们要在 render 函数处理条件或循环只能使用js 中的 if 和 for

Vue.component('comp', {
    data: () {
        return {
            msg: 'my comp'
        }
    },
    render (h) {
        if (this.msg) {
            return h('div', this.msg)
        }
        return h('div', 'bar')
    }
})
复制代码

parse 函数总结

parse函数在处理的过程中,会依次遍历模板字符串,把html模板字符串转换为ast对象,html中的属性页指令都会被存储在ast对应的属性上

求赞.jpeg

猜你喜欢

转载自juejin.im/post/7066383771943043102