vue3源码解读--compile

\bullet 目录

    vue2源码

    vue3源码

\bullet 示例

\bullet 源码

    个人感觉应该是和vue2的实现总体一致的,故也按照这个思路来看


    \equiv 生成ast tree


    将代码定位到compile函数,其接收入参为html标签的字符串形式(示例是直接使用的字符串,故不需要经过vue-loader的解析)和一些编译配置,即编译入口

(extend其实和Object.assign的功能类似)

    接着又做了一些辅助函数的合并,用于编译时调用,如onError函数用于在出错时抛出错误信息

    接着进入baseParse函数,查看具体的解析流程

    createParserContext函数除了向options又添加了一些辅助api外,比较关键的一点是提供了template模板的标识位,比如初始时标识在第一行第一列,左侧无空格。

(经过部分解析后右移和下移,以确定当前处理位置)

    getCursor则相当于对上一步的返回对象进行了解构,获取到上图匡红的三个标识位

    接着进入parseChildren,这应该是一个比较核心的函数了

(之所以一开始就直接执行parseChildren ,是因为vue3支持多根节点,如果是vue2的单根节点的话,则应该是先parseElement 后进入parseChildren )

        从last函数可以推测出,vue每解析出一个元素就会将结果push进队列,由于对于嵌套元素而言,一定是先父元素的start标签再子元素的start标签,所以前一个必定是其父元素。当然,要保证这样一个前提,就必然需要在匹配到end标签的时候做对应的pop或shift操作。那接下来就具体来验证下猜想

    进入while循环,正常来说都是正常的html元素标签

    进入parseElement,通过注释可以看出,标签的解析分为开始标签、子元素、结束标签三部分进行处理

    \alpha 开始标签的处理

        \ast 解析标签,校正标识位并将已经处理的字符从源字符中删除

        \ast 解析标签属性,如class、id等,当前示例没有属性,故进行下修改

            从代码可以看出,这主要包含三个步骤:

                I-正则匹配id并保存至name

                II-获取value的值

                III-识别vue内置属性并处理

        \ast 解析结果如下

    \beta 子元素的处理

        这会再次调用parseChildren对子元素作处理,对于子元素的开始标签而言,其处理逻辑和上边分析的一致。注意,此时的ancestors是有值的,值为上一个div的头标签,本次作为子元素的父元素(注意,当前非内置的html元素,在render和patch过程中将走mountComponent流程)

        这显然会进行又是一次递归parseChildren的过程

        最终得到的结果如下

(两个换行会被剔除)

    代码回到id=appWrapper所在的parseElement中,将解析到的子元素信息通过children保留,以完成ast tree的创建

    \gamma 结束标签的处理

        结束标签没有对属性的处理,因此只是单纯的在校正标识位,并做一些必要的错误校验

        此时得到的完整的ast tree如下


    \equiv ast tree补充


    这一步我感觉是在对ast树做补充处理,它将一些只被vue识别的属性添加到了上边


    \equiv 生成代码字符串


        生成代码字符串的过程其实和vue2差不多,也是在对ast tree进行解析,碰到不同的标识转换成不同的处理函数,最后通过new Function()的形式将其转换为可执行代码作为render函数在组件构建过程中被调用

        当前生成的render函数如下

\bullet 总结

    模板编译就是对tenplate做分析,将符合vue语法规范的东西找出来

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容