JavaScript设计模式:观察者模式

卡米洛·雷耶斯
分享

在JavaScript中,有一个经常出现的问题。您需要一种方法来更新页面的某些部分以响应某些事件,并使用这些事件提供的数据。例如,您可以将用户输入投影到一个或多个组件中。这将导致代码中的大量推拉操作以保持所有内容的同步。

这就是观察者设计模式可以提供帮助的地方——它支持元素之间的一对多数据绑定。这种单向数据绑定可以是事件驱动的。使用这种模式,您可以构建可重用的代码来解决您的特定需求。

在本文中,我将探讨观察者设计模式。它将帮助您解决在客户端脚本中常见的问题。这是一对多、单向、事件驱动的数据绑定。当您有许多必须同步的元素时,这是一个经常出现的问题。

我将使用ECMAScript 6来说明这个模式。是的,将会有类、箭头函数和常量。如果您还不熟悉这些主题,请随意探索。我将只使用ES6中引入语法糖的部分,因此如果需要,它可以移植到ES5中。

我将使用测试驱动开发(TDD)来处理该模式。通过这种方式,您可以了解每个组件的用处。

ES6中的新语言特性使得代码更加简洁。让我们开始吧。

事件观察者

模式的高级视图如下所示:

│├──unsubscribe:清除可观察事件。|├──broadcast:执行所有绑定数据的事件

在我充实观察者模式之后,我将添加一个使用它的字数。单词计数组件将使用该观察者并将其全部组合在一起。

初始化EventObserver做的事:

EventObserver构造函数观察人士

从观察到的事件的空列表开始,并对每个新实例执行此操作。从现在开始,让我们在里面添加更多的方法EventObserver充实设计模式。

订阅方法

要添加新事件,请执行:

订阅fn观察人士fn

获取观察到的事件列表,并将一个新项目推入数组。事件列表是一个回调函数列表。

在纯JavaScript中测试这个方法的方法如下:

/ /安排常量观察者EventObserver常量fn=>/ /行为观察者订阅fn/ /维护断言strictEqual观察者观察人士长度,1

我使用节点的断言在Node中测试该组件。完全相同的断言存在于柴断言了。

注意,观察到的事件列表由简单的回调组成。然后检查列表的长度,并断言回调函数在列表上。

退订方法

要删除事件,请执行:

退订fn观察人士观察人士过滤器订阅者=>订阅者= = !fn

从列表中过滤出与回调函数匹配的内容。如果没有匹配,回调将保留在列表中。过滤器返回一个新的列表并重新分配观察者列表。

要测试这个不错的方法,请执行:

/ /安排常量观察者EventObserver常量fn=>观察者订阅fn/ /行为观察者退订fn/ /维护断言strictEqual观察者观察人士长度,0

回调函数必须与列表中的相同函数匹配。如果有匹配项,则unsubscribe方法将其从列表中删除。注意,测试使用函数引用来添加和删除它。

广播法

调用所有事件做:

广播数据观察人士forEach订阅者=>订阅者数据

这将遍历观察到的事件列表并执行所有回调。这样,您就获得了与订阅事件之间必要的一对多关系。你通过了数据参数,该参数使回调数据绑定。

ES6使用箭头函数使代码更加有效。注意(subscriber) => subscriber(data)函数来完成大部分工作。这个一行箭头函数得益于这种简短的ES6语法。这是JavaScript编程语言的明显改进。

要测试此广播方法,请执行以下操作:

/ /安排常量观察者EventObserversubscriberHasBeenCalled常量fn数据=>subscriberHasBeenCalled数据观察者订阅fn/ /行为观察者广播真正的/ /维护断言subscriberHasBeenCalled

使用而不是常量所以我们可以改变变量的值。这使得变量可变,允许我在回调中重新分配它的值。使用一个在你的代码中向其他程序员发送一个信号,表明变量在某个时刻发生了变化。这增加了JavaScript代码的可读性和清晰度。

这个测试给了我必要的信心,以确保观察者按照我的预期工作。使用TDD,就是用纯JavaScript构建可重用代码。用纯JavaScript编写可测试代码有很多好处。测试所有内容,并保留有利于代码重用的内容。

有了这个,我们充实了EventObserver.问题是,你能用它来做什么?

观察者模式在行动:博客字数统计演示必威滚

对于演示,是时候放置一篇博客文章了,它可以为您记录字数。必威滚您作为输入输入的每一次击键都将被观察者设计模式同步。可以把它看作是免费的文本输入,每个事件都会向您需要的地方发送更新。

要从自由文本输入中获得字数,可以这样做:

常量getWordCount文本=>文本?文本修剪分裂/\ s +/长度0

完成了!在这个看似简单的纯函数中有很多内容,那么简单的单元测试如何?这样就很清楚我想要做什么:

/ /安排常量必威滚博客“这是一篇有字数统计的必威滚博客文章。”/ /行为常量getWordCount必威滚博客/ /维护断言strictEqual,9

注意里面有些古怪的输入字符串必威滚博客.我想让这个函数覆盖尽可能多的边缘情况。只要它能给我一个正确的字数,事实上,我们正在朝着正确的方向前进。

顺便说一句,这就是TDD的真正力量。可以迭代此实现并覆盖尽可能多的用例。单元测试告诉您我期望它如何表现。如果行为有缺陷,无论出于什么原因,都很容易迭代和调整它。通过测试,有足够的证据让其他人做出改变。

是时候将这些可重用组件连接到DOM了。在这里,您可以使用纯JavaScript并将其直接焊接到浏览器中。

一种方法是在页面上有以下HTML:

<文本区域id必威滚博客占位符进入你的博客文章…必威滚必威滚博客>文本区域>

接下来是这个JavaScript:

常量wordCountElement文档createElement“p”wordCountElement类名称“wordCount”wordCountElementinnerHTML'Word Count: 0'文档身体列表末尾wordCountElement常量必威滚blogObserverEventObserver必威滚blogObserver订阅文本=>常量必威滚blogCount文档getElementById“必威滚blogWordCount”必威滚blogCounttextContentgetWordCount文本常量必威滚博客文档getElementById“必威滚博客”必威滚博客addEventListener“弹起”,=>必威滚blogObserver广播必威滚博客价值

把所有可重用的代码放到观察者设计模式中。这将跟踪文本区域的变化,并在其正下方为您提供字数统计。我用的是body.appendChild ()在DOM API中添加这个新元素。然后,附加事件侦听器以使其活起来。

注意与箭头功能可以将一行程序事件连接起来。实际上,您可以使用此命令向所有订阅者广播事件驱动的更改。的() => 必威滚blogObserver.broadcast()这里的大部分工作都是他干的。它甚至将对文本区域的最新更改直接传递给回调函数。是的,客户端脚本非常酷。

没有一个你可以触摸和调整的演示是不完整的,下面是CodePen:

看钢笔观察者模式由Si必威西盟体育网页登录tePoint (@必威西盟体育网页登录SitePoint)CodePen

现在,我不认为这个功能是完整的。它只是观察者设计模式的起点。我脑子里的问题是,你愿意走多远?

展望未来

这取决于你把这个想法更进一步。有许多方法可以使用观察者设计模式来构建新特性。

你可以增强演示:

  • 另一个计算段落数的组件
  • 另一个显示输入文本预览的组件
  • 例如,用降价支持增强预览

这些只是你可以做的一些想法,让你更深入地了解这个问题。上述增强将挑战您的编程能力。

结论

观察者设计模式可以帮助您用JavaScript解决实际问题。这解决了长期存在的保持一堆元素与相同数据同步的问题。通常情况下,浏览器触发特定事件。我相信你们大多数人现在都遇到过这样的问题,并且已经开始使用工具和第三方依赖关系。

这种设计模式可以让你的想象力发挥到极致。在编程中,您将解决方案抽象为模式并构建可重用代码。你能走多远是没有限制的。

我希望您能明白,通过一点纪律和努力,您可以在纯JavaScript中完成多少工作。该语言中的新特性(如ES6)可以帮助您编写一些可重用的简洁代码。

本文由朱里奥曼拉德.感谢所有SitePoint的同行审必威西盟体育网页登录稿人,让SitePoint的内容成为最好的!

Ruby中的设计模式:观察者,单例"></a>
         <div class= Ruby中的设计模式:观察者,单例 蒂亚戈Jackiw
模块化设计模式:JavaScript中的私有、特权和受保护成员"></a>
         <div class= 模块化设计模式:JavaScript中的私有、特权和受保护成员 詹姆斯•爱德华兹
理解观察者模式"></a>
         <div class= 理解观察者模式 伊格内修斯张志贤
一个我不能没有的JavaScript设计模式"></a>
         <div class= 一个我不能没有的JavaScript设计模式 詹姆斯•爱德华兹
Baidu