Vue.js设计与实现——取舍的艺术
文章基于Vue.js核心团队成员新书学习,加上个人理解,并没有完全照搬书中的代码和文字。深度学习推荐购买正版《Vue.js 设计与实现》。Imperative和declarative命令式编程侧重于过程,一个典型的命令式编程库jQuery:
//获取id为app的div标签$('#app')//settexttypeishelloworld.text('helloworld')//点击时,内容变为hellojquery.on('click',function(){this.innerText='hellojquery'})命令式编程比较多符合Ordinary的思路,直接操作DOM,性能更好。声明式编程关注结果,比如Vue:
{{content}} 声明式编程符合UI=f(x)的功能思想,数据驱动视图,UI修改过程交给框架,开发者只需要关注变量,减少维护时的精神负担。总结:声明式编程更易于维护,但其性能低于命令式。Vue要做的是在保持可维护性的同时尽量减少性能损失。虚拟DOM的表现Vue在第一次渲染视图的时候会生成一个VNode,更新的时候会生成一个新的VNode。比较新旧VNode,找出修改差异最小的,让其修改。因此:声明式代码的更新性能消耗=找不同的性能消耗+修改DOM的性能消耗理论上直接用原生JavaScript操作DOM性能更好,但这对开发者的能力要求更高。在使用jQuery期间,经常会有很多innerHTML的暴力操作。虚拟DOM首次渲染时性能对比耗时=创建JavaScript对象(VNode)+全DOM渲染innerHTML耗时=拼接JavaScript字符串+全DOM渲染虚拟DOM更新时耗时=新建JavaScript对象性能对比(VNode)+Diff+部分DOM渲染innerHTML耗时=拼接JavaScript字符串+全DOM渲染总结操作虚拟DOM和操作原生DOM,谁的性能更好,无法简单下结论。因为关系到怎么操作DOM,什么时候操作DOM,修改多少。VirtualDOM是保证运行性能、代码可维护性、减轻精神负担的综合选择。运行时和编译时纯运行时手写DOM对象,运行时直接遍历对象进行渲染,但是写起来比较麻烦。varvnode={tag:'div',children:[{tag:'span',children:'hello'},{tag:'span',children:'vue'}]}functionrender(vnode,parent){constel=document.createElement(vnode.tag)constchildren=vnode.childrenif(typeofchildren==='string'){el.innerHTML=vnode.children}if(Array.isArray(children)&&children.length!==0){children.forEach(child=>{render(child,el)})}parent.appendChild(el)}render(vnode,document.body)编译时+运行时开发时编写纯HTML模板:
hellovue
构建时通过编译器编译:consthtmlString='
...
'constcontent=compile(htmlString)运行时渲染:render(content,document.body)纯编译时,我们可以将模板编译成渲染函数或者VNode,也可以直接编译成原生DOM操作:consthtmlString='
...
'constcontent=compilee(htmlString)//编译生成constdiv=document.createElement('div')consthello=document.createElement('span')hello.innerHTML='hello'div.appendChild(hello)//...总结pureruntime和compile-time+runtime方式都可以通过不同的渲染器实现跨平台渲染,灵活性高但是纯runtime写起来麻烦。如果要做静态优化,需要手动标记,编译时+运行时可以交给编译器去做。纯编译理论上可以达到最好的性能,但是灵活性比较弱。综上所述,Vue是一个编译时+运行时声明式UI框架,它使用虚拟DOM进行更新渲染。保证具有良好的可维护性和灵活性,加上静态优化,尽可能接近原生性能。