美文网首页
vue的编译器到真实dom到过程。

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

作者: janezhang | 来源:发表于2020-04-05 11:42 被阅读0次

一、处理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值。

  1. 静态的class值。即原来就固定写好的值。比如:staticClass: ""static""
  2. rawAttrsMap:这个不是很明白。指令吗?
    以下这个图 是ast部分语法图


    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 )

Vue.compile( template )

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

var res = Vue.compile('<div><span>{{ msg }}</span></div>')

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.


image.png

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

patch成真实dom脑图链接:

整体流程如下:

Template: html代码— 通过parse()
Ast: 语法树,— 变成JS 描述的DOM。—> transform()
Transform: vue特有的语法转化
Generate:生成最终的执行代码
上图:

image.png

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

vue异步更新dom流程2.png

相关文章

网友评论

      本文标题:vue的编译器到真实dom到过程。

      本文链接:https://www.haomeiwen.com/subject/gnedphtx.html