做证券考试的网站,博客和网站有什么不同,国外做图标网站,wordpress4.3下载Vue模板编译
Vue生命周期中#xff0c;在初始化阶段各项工作做完之后调用了vm.$mount方法#xff0c;该方法的调用标志着初始化阶段的结束和进入下一个阶段#xff0c;从官方文档给出的生命周期流程图中可以看到#xff0c;下一个阶段就进入了模板编译阶段(created和befor…Vue模板编译
Vue生命周期中在初始化阶段各项工作做完之后调用了vm.$mount方法该方法的调用标志着初始化阶段的结束和进入下一个阶段从官方文档给出的生命周期流程图中可以看到下一个阶段就进入了模板编译阶段(created和beforeMounted之间的阶段)该阶段所做的主要工作是获取到用户传入的模板内容并将其编译成渲染函数生成模板字符串。然后将这些模板字符串转换成内存中的DOM。
一、Vue 编译原理这块的整体逻辑主要分三个部分 1.将模板字符串转换成element AST(抽象语法树解析器parser 2.对AST进行静态节点标记主要用来做虚拟dom的渲染优化优化器optimizer 3.使用element AST 生成render函数代码字符串代码生成器code generator 伪代码
// main.js文件
new Vue({el: #app,templete: divhello world/div, //可选render: h h(App), //渲染函数
}).$mount(#app) //挂载函数Vue.prototype.__init function (options) {const vm this;vm.$options options;initState(vm);if (vm.$options.el) {//$mount 挂载函数vm.$mount(vm.$options.el)}
}Vue.prototype.$mount function (el) {const vm this, options vm.$options;el document.querySelector(el);vm.$el el;if (!options.render) {let templete options.templete; //是否有templete选项if (!templete el) {templete el.outerHTML}//把这个模板变成render函数const render compileToRenderFunction(templete); //把HTML转化成SAT树options.render render;}}解析器AST在线生成
div classcontainer idrootp classname{{name}}/p
/div上面一个简单 的模版转换成element AST树形结构后是这样的
{tag: divtype: 1,staticRoot: false,static: false,plain: true,parent: undefined,attrsList: [{name:class,value:container},{name:id:value:root}],attrsMap: {},children: [{tag: ptype: 1,staticRoot: false,static: false,plain: true,parent: {tag: div, ...},attrsList: [{name:class, value:name}],attrsMap: {},children: [{type: 2,text: {{name}},static: false,expression: _s(name)}]}]
}我们可以看到上面的dom被解析成了解析器它的原理主要是两部分内容一部分是截取字符串一部分是对截取的字符串做解析。
优化器
优化器的目的就是找出那些静态节点并打上标记而静态节点指的是DOM不需要发生变化的节点也就是里面都是静态标签和静态文本。
标记静态节点有两个好处
一、每次重新渲染的时候不需要为静态节点创建新节点也就是静态节点的解析器不需要重新创建二、在虚拟 DOM中patching的过程可以被跳过
优化器的实现原理主要分两步
一、用递归的方式将静态节点添加static属性用来标识是不是静态节点二、标记所有静态根节点(子节点全是静态节点就是静态根节点)
代码生成器
代码生成器的作用是使用element ASTs生成render函数代码字符串带有__c, v, _s 使用本文开头举的例子中的模版生成后的AST来生成render后是这样的
{render: with(this){return _c(div,[_c(p,[_v(_s(name))])])
}
}生成后的代码字符串中看到了有几个函数调用_c、_v、_s。 _c对应的是createElement它的作用是创建一个元素。 1.第一个参数是一个HTML标签名 2.第二个参数是元素上使用的属性所对应的数据对象可选项 3.第三个参数是children _v的意思是创建一个文本节点。 _s是返回参数中的字符串。 代码生成器的总体逻辑其实就是使用element ASTs去递归然后拼出这样的_c(‘div’,[_c(‘p’,[_v(_s(name))])]) 字符串。 问题在模板编译的阶段是不是就会对每个组件所使用的data或者computed值进行访问从而创建新的Watcher进行订阅然后对应的属性的dep就会收集这些watcher从而实现更新的 答不是的模板编译只是会把模板编译成渲染函数只有在渲染函数被执行的时候才会对数据进行访问而渲染函数是在watche实例中执行的所以渲染函数中所使用到的所有数据都会被同一个Watcher监听当这些状态发生变化时会通知这个Watcher这个Watcher会触发VirtualDOM对组件进行渲染。一个组件的模板会被编译成一个渲染函数。每个组件有一个Watcher用来监听模板中所使用到的数据、当这些数据发生变化时通过VirtualDOM进行更新组件的视图