响应性本质上是关于系统如何对数据变化作出反应,有不同类型的响应性。然而,在这篇文章中,我们关注的是响应性,即响应数据变化而采取行动。
作为一名前端开发者,Pavel Pogosov 每天都要面对这个问题。因为浏览器本身是一个完全异步的环境。现代 Web 界面必须快速响应用户的操作,这包括更新 UI、发送网络请求、管理导航和执行各种其他任务。
尽管人们常常将响应性与框架联系在一起,Pavel Pogosov 认为通过纯 JavaScript 实现响应性可以学到很多。所以,我们将自己编写一些模式代码,并研究一些基于响应性的原生浏览器 API。
目录
- PubSub(发布-订阅模式)
- 自定义事件作为浏览器版本的 PubSub
- 自定义事件目标
- 观察者模式
- 使用 Proxy 的响应式属性
- 单个对象属性和响应性
- 使用 MutationObserver 的响应式 HTML 属性
- 使用 IntersectionObserver 的响应式滚动
1. PubSub(发布-订阅模式)
一个常见的使用示例是 Redux。这款流行的状态管理库基于这种模式(或更具体地说,是 Flux 架构)。在 Redux 的上下文中,工作机制相当简单:
发布者:store 充当发布者。当一个 action 被派发时,store 会通知所有订阅的组件状态的变化。 订阅者:应用程序中的 UI 组件是订阅者。它们订阅 Redux store 并在状态变化时接收更新。
自定义事件作为浏览器版本的 PubSub
浏览器通过 CustomEvent 类和 dispatchEvent 方法提供了一个用于触发和订阅自定义事件的 API。后者不仅能让我们触发事件,还能附加任何想要的数据。
自定义事件目标
如果你不想在全局 window 对象上分派事件,可以创建你自己的事件目标。
通过扩展原生 EventTarget 类,你可以向其新实例分派事件。这确保你的事件仅在新类本身上触发,避免了全局传播。此外,你可以直接将处理程序附加到这个特定实例上。
观察者模式
观察者模式与 PubSub 非常相似。你订阅 Subject,然后它通知其订阅者(观察者)关于变化,使他们能够做出相应的反应。这种模式在构建解耦和灵活的架构中发挥了重要作用。
使用 Proxy 的响应式属性
如果你想对对象的变化做出反应,Proxy 是一个好方法。它让我们在设置或获取对象字段的值时实现响应性。
单个对象属性和响应性
如果你不需要跟踪对象中的所有字段,可以使用 Object.defineProperty 或一组 Object.defineProperties 来选择特定的一个或几个。
使用 MutationObserver 的响应式 HTML 属性
在 DOM 中实现响应性的一种方法是使用 MutationObserver。其 API 允许我们观察目标元素及其子元素的属性变化和文本内容变化。
使用 IntersectionObserver 的响应式滚动
IntersectionObserver API 允许对目标元素与另一个元素或视口区域的交集做出反应。