资讯专栏INFORMATION COLUMN

【Vue原理】Compile - 白话版

dingding199389 / 900人阅读

摘要:写文章不容易,点个赞呗兄弟专注源码分享,文章分为白话版和源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于版本如果你觉得排版难看,请点击下面链接或者拉到下面关注公众号也可以吧原理白话版终于到了要讲白话的时候了

写文章不容易,点个赞呗兄弟  


专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧
研究基于 Vue版本 【2.5.17】

如果你觉得排版难看,请点击 下面链接 或者 拉到 下面关注公众号也可以吧

【Vue原理】Compile - 白话版

终于到了要讲 compile 白话的时候了,大家准备好了吗,白话版肯定不会很复杂啦,源码版就不一定了。。。

源码版我写了9篇啊!每篇的篇幅都很长啊!!我都快写奔溃了啊!!

都快坚持不下来了,我算了算, compile 的源码版,我好像快写了一个多月???

卧槽,竟然写了这么久.....

好吧,现在开始我们的正文

Compile

compile 的内容非常多,大致分为三块主要内容,我也称他们是Vue的 渲染三巨头

就是 parse,optimize,generate

虽然分为三块,但是要明确一点

compile 的作用是解析模板,生成渲染模板的 render

比如这样的模板

经过 compile 之后,就会生成下面的 render

_c("div", [_c("span"), _v(num)])

而 render 的作用,也是为了生成跟模板节点一一对应的 Vnode

{    

    tag: "div",    

    children:[{        

        tag: "span",        

        text: undefined

    },{        

        tag: undefined

        text: "111"
    }]
}

下面我们就来一个个看渲染三巨头

Parse

这是 compile 的第一个步骤

作用是

接收 template 原始模板,按照模板的节点 和数据 生成对应的 ast

比如这样

生成的 ast 是这样,所有模板中出现的数据,你都可以在 ast 中找到

{    

    tag: "div",    

    attrsMap: {test: "2"},    

    children:[{        

        tag: "span",        

        children: [],        

        attrsMap: {name: "1"}

    }]
}

ast 是什么?个人简单理解的话

以数据的形式去描述一个东西的所有的特征吧,说错别打我

比如说ast 描述我

{    

    name: "神仙朱",    

    sex: 1,

    desc: "一个靓仔"

}

具体可以查一下,相关内容挺多的

另外,这里不会讲细节,parse 是怎么生成 ast 的,因为涉及很多源码,放在源码版了

Optimize

这是 compile 的第二步

作用是

遍历递归每一个ast节点,标记静态的节点(没有绑定任何动态数据),

这样就知道那部分不会变化,于是在页面需要更新时,减少去比对这部分DOM

从而达到性能优化的目的

比如这个模板

span 和 b 就是静态节点,在 optimize 处理中,就会给他们添加 static 判断是否是静态节点

{    

    static: false,    

    staticRoot: false,    

    tag: "div",    

    children: [{        

        staticRoot: true,        

        tag: "span",        

        children: [{            

            static: true,            

            tag: "b"

        }]
    },{        

        static: false,        

        text: "{{a}}"

    }]
}

而你也看到一个属性,staticRoot,这个是表示这个节点是否是静态根节点的意思

用来标记 某部分静态节点 最大的祖宗节点,后面更新的时候,只要碰到这个属性,就知道他的所有子孙节点都是静态节点了,而不需要每个子孙节点都要判断一次浪费时间

具体是怎么做的,感兴趣的话欢迎看以后的源码版

Generate

这是 compile 的第三步

作用是

把前两步生成完善的 ast 组装成 render 字符串(这个 render 变成函数后是可执行的函数,不过现在是字符串的形态,后面会转成函数)

看个例子

经过前两步变成 ast

{    

    static: false,    

    staticRoot: false,    

    tag: "div",    

    children: [{        

        static: false,        

        staticRoot: false,        

        tag: "span",        

        children: [{            

            static: false,            

            text: "{{b}}"

        }]
    },{        

        static: false,        

        text: "{{a}}"

    }]
}

然后,generate 接收 ast,先处理最外层 ast,然后开始递归遍历子节点,直到所有节点被处理完

这个过程中,字符串会被一点一点拼接完成,比如上面的 ast 拼接结果就是下面这样

_c 是生成节点对应的 Vnode 的一个函数

`
_c("div", [
    _c("span", [
        _v(b)
    ]),
    _v(a)
])
`
简单说一下拼接流程

1、一开始接收到 ast,处理最外层 ast 这个点,是 div,于是拼接得到字符串

code  = ` _c("div", [  `

2、遍历 div 子节点,遇到 span,拼接在 div 的子节点数组中

code = `_c("div", [  _c("span", [ `

3、开始处理 span 的子节点 b,放进 span 的 子节点数组中

code = ` _c("div", [  _c("span", [  _v(b)  `

4、span 子节点处理完,闭合 span 的 子节点数组

code = ` _c("div", [  _c("span", [  _v(b) ] `

5、继续处理 span 同级 的子节点,是个文本节点,但是是动态值,变量是 a

code = `_c("div", [  _c("span", [  _v(b) ] , _v(a)  `

6、所有子节点都处理完毕,闭合 div 的 子节点数组

code = ` _c("div", [  _c("span", [  _v(b) ] , _v(a) )]  `
render转成函数

前面两步把 template 解析生成了 render 字符串,但是需要执行的话,还是需要转换成函数的

怎么转呢?就是下面这样

render = new Function(render)

然后 render 保存在实例上,具体位置是

vm.$options.render

至此,compile 所有的功能就完成了

而关于 render 的内容,比如说 render 中出现的各种函数是什么,会专门放在 render 的文章去记录

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/106566.html

相关文章

  • Vue原理Compile - 源码 之 Parse 标签解析

    摘要:当字符串开头是时,可以匹配匹配尾标签。从结尾,找到所在位置批量闭合。 写文章不容易,点个赞呗兄弟 专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于 Vue版本 【2.5.17】 如果你觉得排版难看,请点击 下面链接 或者 拉到 下面关注公众号也可以吧 【Vue原理】Compile - 源码版 之 标签解析...

    loostudy 评论0 收藏0
  • Vue原理Compile - 源码 之 Parse 主要流程

    写文章不容易,点个赞呗兄弟 专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于 Vue版本 【2.5.17】 如果你觉得排版难看,请点击 下面链接 或者 拉到 下面关注公众号也可以吧 【Vue原理】Compile - 源码版 之 Parse 主要流程 本文难度较繁琐,需要耐心观看,如果你对 compile 源码暂时...

    Forest10 评论0 收藏0
  • Vue原理Compile - 源码 之 从新建实例到 compile结束的主要流程

    摘要:页面这个实例,按理就需要解析两次,但是有缓存之后就不会理清思路也就是说,其实内核就是不过是经过了两波包装的第一波包装在中的内部函数中内部函数的作用是合并公共和自定义,但是相关代码已经省略,另一个就是执行第二波包装在中,目的是进行缓存 写文章不容易,点个赞呗兄弟 专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于 ...

    CODING 评论0 收藏0
  • Vue原理Compile - 源码 之 generate 节点拼接

    摘要:还原的难度就在于变成模板了,因为其他的什么等是原封不动的哈哈,可是直接照抄最后鉴于本人能力有限,难免会有疏漏错误的地方,请大家多多包涵,如果有任何描述不当的地方,欢迎后台联系本人,有重谢 写文章不容易,点个赞呗兄弟 专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于 Vue版本 【2.5.17】 如果你觉得排版...

    macg0406 评论0 收藏0
  • Vue原理Compile - 源码 之 generate 节点数据拼接

    摘要:写文章不容易,点个赞呗兄弟专注源码分享,文章分为白话版和源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究基于版本如果你觉得排版难看,请点击下面链接或者拉到下面关注公众号也可以吧原理源码版之节点数据拼接上一篇我们 写文章不容易,点个赞呗兄弟 专注 Vue 源码分享,文章分为白话版和 源码版,白话版助于理解工作原理,源码版助于了解内部详情,让我们一起学习吧研究...

    fizz 评论0 收藏0

发表评论

0条评论

dingding199389

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<