vue html parser,vue的编译器到真实dom到过程。

一、处理template里的或者html字符串通过parse()成为ast语法树。

parse():

parseHTML(): 这2个函数是:处理html的过程,通过遍历html元素,得到所有的元素对象,分别区分处理元素,属性,指令等ast语法。具体结构如下:

1.元素类型 1.或3

2.元素tag值。div

3 .属性值:a.数组类型(attrsList),b.对象类型。(attrsMap)

4 .父元素: parent

5.子元素: children

6.classBinding。样式的名称key值。

静态的class值。即原来就固定写好的值。比如:staticClass: ""static""

rawAttrsMap:这个不是很明白。指令吗?

以下这个图 是ast部分语法图

1f39b3fd660c

image.png

二、再将ast语法树,通过Transform()处理vue特有语法,再通过genrate()编译成 render 函数。。运行_c的时候就会读取响应的data值。然后再作对应变量值的对应渲染树,watcher

generate(ast, options):

genElement(ast) : '_c("div")':主要处理ast元素里面的指令,v-if,slots等。涉及多个处理指令的函数如下

这上面2个函数是处理上面的ast结构的

return genStatic(el, state)

return genOnce(el, state)

return genFor(el, state)

return genIf(el, state)

return genChildren(el, state) || 'void 0'

return genSlot(el, state)

然后在把上面的ast 经过var code = generate(ast, options);处理得到可执行的code。

通过下面2个函数,加上上面的ast入参,产生如下。

下面的_c里面包含很多变量,关于data里的,props,

//genElement产出的code值如下:

"_c('div',{class:[activeClass, errorClass]},[_v("hello ,喂。。数组语法 。")])"

"_c('div',{staticClass:"static",class:{ active: isActive, 'text-danger': hasError }},[_v("\n 对象方式\n ")])"

"_c('div',{class:[isActive ? activeClass : '', errorClass]},[_v("数组形式,的三元运算")])"

"_c('div',{attrs:{"id":"demo"}},[_c('form',{attrs:{"id":"search"}},[_v("\n Search "),_c('input',{directives:[{name:"model",rawName:"v-model",value:(searchQuery),expression:"searchQuery"}],attrs:{"name":"query"},domProps:{"value":(searchQuery)},on:{"input":function($event){if($event.target.composing)return;searchQuery=$event.target.value}}})]),_v(" "),_c('demo-grid',{attrs:{"data":gridData,"columns":gridColumns,"filter-key":searchQuery}})],1)"

// 编译字符串。。。

function baseCompile(

template,

options

) {

var ast = parse(template.trim(), options);

optimize(ast, options);

var code = generate(ast, options);

return {

ast: ast,

render: code.render,

staticRenderFns: code.staticRenderFns

}

}

相当于以上2个步骤是vue暴露出来的接口:Vue.compile( template )

用法如下:适用于要编程式写法代替html模板写法。

var res = Vue.compile('

{{ msg }}
')

var a = new Vue({

data: {

msg: 'hello'

},

render: res.render,

staticRenderFns: res.staticRenderFns

})

a.$mount('#app');

等同于vue.compile方法内部的使用方式如下(摘用了vue.$mount的里面部分源码):

var ref = compileToFunctions(template, {

shouldDecodeNewlines: shouldDecodeNewlines,

delimiters: options.delimiters

}, this);

//得到一个 渲染dom的函数

var render = ref.render;

var staticRenderFns = ref.staticRenderFns;

options.render = render;

options.staticRenderFns = staticRenderFns;

三、vm._render()产生虚拟dom

上面通过了ast,_c()写法 然后产生了虚拟dom.

1f39b3fd660c

image.png

四。vm.$el = vm.patch(prevVnode, vnode);变成了真实的dom.

整体流程如下:

Template: html代码— 通过parse()

Ast: 语法树,— 变成JS 描述的DOM。—> transform()

Transform: vue特有的语法转化

Generate:生成最终的执行代码

上图:

1f39b3fd660c

image.png

五。vue异步更新dom的过程、patch真实dom的过程 脑图

1f39b3fd660c

vue异步更新dom流程2.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值