系列之颜色选择器(一):内部事件

1,185 阅读4分钟

前言

最近接到一个任务,通过第三方库的形式写一个颜色选择器并引入 wangEditor,以此优化 wangEditor 当前字体颜色和背景颜色功能。

为了方便理解,我定义了一些名词

一:准备工作

我这里是用的 TypeScript + webpack 进行扩展库的开发(学以致用),具体的配置流程就不讲了。如果有需要,可以直接在 GitHub 上拉取 chore 分支即可使用,该分支是一个干净的分支。

二:分析下功能

内部事件主要是为了支撑颜色选择器这一块儿的内部事件。最近学了一些数据结构和模式,打算学以致用。

用过颜色选择器的应该都有一定的经验:

  • 色域滑块被拖动时,我们的色值面板、透明度条、预览框和输出框都同步更新
  • 色值滑块拖动时,我们的透明度条、预览框和输出框都同步更新
  • 透明度滑块拖动时,我们的预览框和输出框都同步更新

结合上面这三点画了一张图,并定义内部的 change 事件

从图上我们可以看到,change的执行顺序是一定的,为了确保顺序的准确性,普通的发布订阅已不再满足需求,所以我想到了事件优先级,也就是今天的主打内容。

1、归纳一下本讲涉及到的知识点:

  • 优先队列(可能有人看腻了)
  • 发布订阅(肯定也有人看腻了)
  • 数组遍历(都看腻了)
  • TypeScript 泛型
  • TypeScript 枚举

2、利用 TypeScript 泛型构建一个优先队列

要写出一个放在那里都可以用的优先队列还是需要一些技巧的,最低效的就是那里用到就在那里定义,这也是我最初的写法(别学),就像这样:

之后呢,你也可能会这样写(也别学),但是完全没这必要,何必去绕那一圈呢!

直接这样写就可以了

3、数组遍历

在发布订阅模式中,我们需要对绑定的事件回调函数进行遍历执行。但是数组自带的 forEach 无法满足我们的需求,所以需要自定义封装一个 forEach

大家在使用 Array.prototype.forEach 是不是有以下体验:

  • 遍历不可以中止
  • 遍历时不可以删除元素,如果删除了元素,会造成索引跳跃的假象,也就是中间会有一项元素未被执行。

结合上面两点,我们可以封装进行如下封装:

4、使用 TypeScript 枚举优化遍历函数

当我们写完自定义 forEach 的时候是不是觉得大功告成了,其实并没有。在使用的时候,你需要记住对应的状态码才能正常使用,一旦你忘记了,就得去翻阅代码或者文档。并且在使用的时候,返回状态码数字会让阅读代码的人很茫然,如下:

在你没有记住返回 0 的作用是什么的时候,你是不是会觉得很茫然,这样的代码大大降低的代码的可读性。如果我们这样实现:

现在再来阅读同样的代码,是不是感觉轻松了很多。再配合完善的注释,阅读代码的时候简直不要太轻松。

值得注意的是,我这里使用了 if...else... 而非 switch,大家可以想一下为什么

5、支持优先级定义的发布订阅

其实这一块儿并没有什么可讲的,就是将发布订阅的数据管理换成优先队列就可以了。不过支持优先级定义的发布订阅可以比普通的发布订阅定义更多的 emit api。比如 emitLessThanemitEqualemitGreaterThan、......

我归纳了以下在发布订阅中需要完成的功能,大家可以参考下:

  • 普通事件绑定:on
  • 一次性事件绑定:once
  • 事件解绑:off
  • 发布事件:emit
  • 发布小于指定等级的事件:emitLessThan
  • 事件清除/全部解绑:clear【可选】

三:最终代码

参考文章

Web开发应该知道的数据结构

这九种常用的设计模式你掌握了吗

观察者模式VS订阅发布模式

结语

这只是我作为一个前端菜鸟的实践,如果有错误的地方欢迎指正。