响应式原理介绍
我们今天来讲讲,啥是响应式,以及Vue是怎么来做到的
广义的响应式
响应式
是一种编程概念(英语:Reactive programming),是一种面向数据流和变化传播的编程范式。这意味着可以在编程语言中很方便地表达静态或动态的数据流,而相关的计算模型会自动
将变化的值通过数据流进行传播
例如 a = b + c, 那么当b的数值发生变化时,a的值会随着b或c的值变化而自动变化
最简单的例子就是Excel
的公式。单元格可以包含字面值或类似"=B1+C1"的公式,而包含公式的单元格的值会依据其他单元格的值的变化而变化
前端中的响应式
响应式
与响应式网页设计
不同
响应式网页设计(英语:Responsive web design,通常缩写为RWD),或称自适应网页设计、回应式网页设计、对应式网页设计。 是一种网页设计的技术做法,该设计可使网站在不同的设备(从桌面计算机显示器到移动电话或其他移动产品设备)上浏览时对应不同分辨率皆有适合的呈现,减少用户进行缩放、平移和滚动等操作行为。我们更多情况下,会将其称为 页面多端适配
前端为什么需要响应式
经常学习东西的时候,不光要埋头前进,还要抬头看路,看看脚下这条路到底通到哪里
在前端展示页面当中,承载渲染输出的载体是HTML,这是一种类xml的超文本语言,内部的数据并不具有类似Excel的响应式刷新的功能,那么在页面越来越复杂的今天,展示静态页面已经远远不能满足我们的需求了
那么如果现在又一个证券交易平台的前端展示页面,要求头部数据随机显示一支涨幅在前十的股票,实时刷新,那么我们会怎么做?
通过querySelector从DOM中找到对应节点,动态的更新数据
没错,这个方法确实ok,那么假如旁边还有一栏需要显示涨幅最高的全部十只股票,并且价格也需要刷新呢,这时候我们刚刚的方法可能就不太奏效了
我们也可以用之前的方法。那么还有两栏也有这几只股票,也需要实时刷新呢?这时候再来一个一个替换,是不是会有点捉襟见肘了
那么假如这十只股票的价格都是响应式的,那么问题就解决了,我们只需要维护一个对象即可,后面所有的数据更新都是响应式的,不需要我们直接一个一个操作DOM了
That's why
Vue中的响应式
前端框架中,这也称为数据绑定,我们的数据和真实的DOM进行了绑定了,这也是个合适的比喻
为了实现上面的响应式,主要有下面几种方法:
- 发布订阅模式(backbone.js)
- 脏值检查(Angular.js)
- 数据劫持 + 发布订阅(Vue.js)
发布订阅
这个模式十分经典了,就是传统的订阅模式
消息的发送者(称为发布者)不会将消息直接发送给特定的接收者(称为订阅者)。而是将发布的消息分为不同的类别,无需了解哪些订阅者(如果有的话)可能存在
脏值检查
原理为通过定时器进行轮询查询,但是只在特定事件触发后进行脏值检测
- DOM事件,譬如用户输入文本,点击按钮等。( ng-click )
- XHR响应事件 ( $http )
- 浏览器Location变更事件 ( $location )
- Timer事件( $timeout , $interval )
- 执行 $digest() 或 $apply()
数据劫持
这就是今天的重点了
劫持,泛指强制占据船舶、汽车等交通工具的控制权,如劫机
ES5中的新api Object.defineProperty 可以劫持所定义数值的 setter 和 getter
let val = 1
Object.defineProperty(data, key, {
set: function(newVal) {
if (val === newVal) return;
console.log('哈哈哈,监听到值变化了 ', val, ' --> ', newVal);
// 我没有劫持set函数,仍有赋值功能
val = newVal;
}
get: function() {
// 我劫持了get函数,每次data[key]只能取到0
return 0
}
});
数据劫持的原理很简单,重点是怎么通过数据劫持实现响应式
当数据被DOM元素读取的时候,我们会触发get函数,那么这个时候我们需要将这个DOM记录一下,这个过程我们有个高大上的解释名词:依赖收集
当数据发生变化的时候,我们会出发set函数,那么,如果要实现数据响应式,set需要做一点工作,更新到上面收集的依赖DOM上,这里也有个高大上的解释名词:派发更新
Vue响应式实现
下面的图来自Vue官网
别看着花里胡哨的,其实不是很复杂。
这里我们先看data,这里的getter setter,就是我们上面介绍的内容
进入data部分的操作是 render ‘Touch’, 指的是在页面初次渲染的时候,我们会使用了这个数据,接下来,getter指向watcher,完成一次依赖收集
TIP
我们的依赖收集和派发更新是交给watcher来进行管理的,这个后续再说明哈
出data的部分,就是setter被触发后,告诉watcher,完成一次派发更新
灰常简单,重点是怎么用js实现,并且无侵入的融入到Vue这个框架内部,这部分在整个框架思路介绍完后,再细讲