前言
最近接到一个任务,通过第三方库的形式写一个颜色选择器并引入 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
。比如 emitLessThan
、emitEqual
、emitGreaterThan
、......
我归纳了以下在发布订阅中需要完成的功能,大家可以参考下:
- 普通事件绑定:on
- 一次性事件绑定:once
- 事件解绑:off
- 发布事件:emit
- 发布小于指定等级的事件:emitLessThan
- 事件清除/全部解绑:clear【可选】
三:最终代码
参考文章
结语
这只是我作为一个前端菜鸟的实践,如果有错误的地方欢迎指正。