读书笔记(九):响应式框架

1.基本原理
数据在变化时不需要开发者去手动更新视图,视图会根据变化的数据自动进行更新。
想完成这个过程,需要做到:知道收集视图依赖了哪些数据、感知被依赖数据的变化、数据变化时自动通知需要更新的视图部分并进行更新。对应的技术为:依赖收集、数据劫持/数据代理、发布/订阅模式。

可以使用Object.defineProperty和Proxy实现拦截,对比之下:

  • Object.defineProperty不能监听数据的变化,需要对数组方法进行重写。
  • Object.defineProperty必须遍历对象的每个属性,且需要对嵌套结构进行深层遍历。
  • Proxy的代理是针对整个对象的,只需要做一层代理就可以监听同级结构下的所有属性变化,当然对于深层结构,递归还是需要进行的。
  • Proxy支持代理数组的变化。
  • Proxy的第二个参数除了可以使用set和get,还可以使用13种拦截方法。
  • 使用Proxy时,性能将会被底层持续优化。

2.模板编译原理
vue中模板变量是通过{{}}表达式输出的,最终的HTML内容应该被合适的数据进行填充替换,因此需要进行编译;比如react中JSX会被编译为React.createElement,并在生成虚拟DOM时进行数据填充。
模板编译是使用正则+遍历的方式,以及一些算法,对#app节点下的内容进行替换,通过正则表达式识别出模板变量,获取对应的数据。双向绑定则是在编译时添加组件的事件监听,并更改数据源。

3.发布订阅模式
js本身就是事件驱动型语言,比如,应用中对一个button进行了事件绑定,用户点击之后就会触发按钮对应的click事件,这是因为此时有特定程序正在监听这个事件,随之触发了相关的处理程序。
这个模式一个好处在于能够对代码进行解耦,实现“高内聚,低耦合”的理念,同样适用于框架设计。

class Notify {
  constructor () {
    this.subscribers = []
  }
  add (handler) {
    this.subscribers.push(handler)
  }
  emit () {
    this.subscribers.forEach(subscriber => subscriber())
  }
}

let notify = new Notify()
notify.add(() => {
  console.log('emit')
})

notify.emit()

4.MVVM
首先对数据进行深度拦截或代理,对每一个属性的getter和setter进行加工。我们需要在模板初次编译时,解析指令(如v-model)并进行依赖收集,订阅数据的变化。
依赖收集的具体过程:当调用替换方法时,读取数据进行模板变量的替换,读取数据时需要做一个标记,用来表示我依赖这一项数据,并订阅这个属性值的变化。比如,vue中通过定义一个Watcher类来表示观察订阅依赖的,模板编译过程会读取数据,进而触发数据源属性值的getter,数据代理的加工就是在数据监听的getter中记录这个依赖,同时在setter触发数据变化时执行依赖对应的相关操作,最终触发模板中的数据变化的。

5.虚拟DOM
用数据结构表示DOM结构,并没有真实挂载到DOM上。好处是操作数据结构远比通过和浏览器交互去操作DOM快,每次通过DOM diff计算出视图前后更新的最小差异,再把最小差异应用到真实DOM上,性能更有保障。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值