《Vue.js设计与实现》第一章 权衡的艺术(读书笔记)

357 阅读2分钟

一、命令与声明,性能与维护

命令式:关注过程

  1. 获取div
  2. 设置文本内容
  3. 添加绑定事件
//jQuery
$('#app').text('hello world').on('click',()=>{alert('ok')})

声明式:关注结果


//Vue
<div @click="()=>alert('ok')">hello world</div>

声明式代码性能不会优于命令式代码的性能。 原因:Vue内部实现也是命令式,总体性能损耗=查找差异的性能+修改的性能。 例如要修改文本内容,Vue需要先找出差异,再通过div.textConten去修改。 框架设计理念:在保持可维护性的同时让性能损失最小化。

如果能尽可能减少查找差异的性能消耗,声明式的性能消耗就会尽可能的接近命令式,这就是虚拟DOM存在的原因。

二、运行与编译

框架设计层面可以分为:运行时,编译时,运行+编译

1.运行时

维护一个树形结构的js对象+可以把js对象转换成DOM节点的Render函数

function Render(obj, root) {
  const el = document.createElement(obj.tag)
  if (typeof obj.children === 'string') {
    const text = document.createTextNode(obj.children)
    el.appendChild(text)
  } else if (obj.children) {
    // array,递归调用 Render,使用 el 作为 root 参数
    obj.children.forEach((child) => Render(child, el))
  }

  // 将元素添加到 root
  root.appendChild(el)
}

const obj = {
  tag: 'div',
  children: [
    { tag: 'span', children: 'hello world' }
  ]
}
// 渲染到 body 下
Render(obj, document.body)

优点:不需要额外学习

缺点:用户需要维护obj这个树形数据结构,不够直观

2.编译时

直接将模板转换成命令式代码

 <div>
    <span>hello world</span>
 </div>
 
const div = document.createElement("div");
const span = document.createElement("span");
span.innerText = "hello world";
div.append(span);
document.body.appendChild(div);

优点:理论上性能更好,直接命令式操作

缺点:不够灵活,无法进行分析优化

3.运行+编译

先把模板编译成虚拟DOM,再通过Render函数渲染成真实DOM(Vue3的)

//1.模板
const html=`
 <div>
    <span>hello world</span>
 </div>
 `
// 2.转换成虚拟对象
const obj=Compiler(html)
    // obj={
    //   tag: 'div',
    //   children: [
    //     { tag: 'span', children: 'hello world' }
    //   ]
    // }
//3.渲染到页面
Render(obj, document.body)
 

优点:可以在编译时分析哪些是长期不会变的部分,提供给Render函数,Render函数进一步会优化渲染过程,更加灵活

缺点:额外的性能开销

三、总结

本章中作者简单介绍了框架设计时的一些概念,命令式声明式,进行了性能和可维护性层面的对比,创建页面,更新页面时需要考虑的性能影响,具体的更新策略要结合心智负担可维护性性能等层面综合考虑。