「.vue文件的编译」5. 模板编译之基于AST的代码生成

2023-02-24 10:31:13 浏览数 (1)

本节偷个懒,可以参考这里

经过前面几个步骤,AST上的维护节点的父子关系,并且每个节点上都有足够的信息。

这里根据这些信息来构造render函数,render函数的形式以demo为例

代码语言:javascript复制
(function anonymous() {
        with (this) {
            return _c('div', {
                staticClass: "container",
                attrs: {
                    "id": "app"
                }
            }, [_c('slot-test', {
                scopedSlots: _u([{
                    key: "header",
                    fn: function (slotProps) {
                        return [_c('div', [_v("name: "   _s(slotProps.user.name))]), _v(" "), _c('div', [_v("sex: "   _s(slotProps.user.sex))])]
                    }
                }])
            }), _v(" "), _c('div', [_v("static node")]), _v(" "), (showSpan) ? _c('span', {
                class: {
                    active: showSpan
                },
                on: {
                    "click": clickHandler
                }
            }, [_v(" show Span")]) : _c('span', {
                on: {
                    "click": clickHandler
                }
            }, [_v("hide Span")]), _v(" "), _l((items), function (item, index) {
                return _c('div', [_c('span', [_v(" "   _s(item))])])
            }), _v(" "), _c('input', {
                directives: [{
                    name: "model",
                    rawName: "v-model",
                    value: (searchText),
                    expression: "searchText"
                }],
                domProps: {
                    "value": (searchText)
                },
                on: {
                    "input": function ($event) {
                        if ($event.target.composing)
                            return;
                        searchText = $event.target.value
                    }
                }
            })], 2)
        }
    }
)

with中的this是vue实例,_u等等都是挂载在该Vue原型上的,_c是直接挂载vm实例上的。

代码语言:javascript复制
// renderMixin -> installRenderHelpers(Vue.prototype)
// initRender -> vm._c = (a, b, c, d) => createElement(vm, a, b, c, d, false)

总结


整个模板解析分为四个步骤

  1. simple-html-parser 来遍历html字符串,找出元素标签(包括收集属性)、文本
  2. 基于simple-html-parser提供的钩子start/end来解析收集来属性,并创建AST节点,将解析后的信息保存到每个AST节点上。并建立AST节点父子关系,root代表整个AST
  3. optimize:不影响主流程,完全是从创建虚拟DOM和虚拟DOM的diff层面来优化这两个步骤(减少虚拟DOM的创建和diff)
  4. 基于砂上面的AST的代码生成,并非还原为html,而是vue需要的render函数,看到关键的方法_c对应运行时的creatElement用来创建虚拟DOM的。

整体看逻辑还是很清晰的。

0 人点赞