ToC
对于已经有一些编程经验的人来说,对 “EventBus” 的概念肯定不陌生,从 Vue2 中使用 new Vue
再到 Vue3 中官方推荐的 mitt
,还有 node 中的 events
模块,都是 EventBus 这个概念的实践,但其实我们每个前端程序员从很早就开始接触这个概念了,只是那时我们还不知道叫这个名字(就像在学设计模式的时候也会恍惚间发现,原来我那次优化后的代码叫xxx模式呀),它就是 DOM 中的事件系统,同时事件系统也是一个标准的发布订阅模式。addEventListener
对应着 on
方法,removeEventListener
则对应着 off
方法。
1<button id="button">button</button>2
3<script>4 const button = document.querySelector('#button')5
6 button.addEventListener('click', alert)7
8 button.removeEventListener('click', alert)9</script>
以上示例代码将事件监听器对象限制为 button
元素,如果我们在框架开发中想要使用 EventBus 来实现夸组件通信的话,我们就可以将事件监听器对象调整为 document
或是 window
。
1<!-- 组件A -->2<button id="button">button</button>3
4<script>5 const button = document.querySelector('#button')6
7 function onButtonClick() {8 document.dispatchEvent(new CustomEvent('toggle'))9 }3 collapsed lines
10
11 button.addEventListener('click', onButtonClick)12</script>
1<!-- 组件B -->2<output id="output"></output>3
4<script>5 const output = document.querySelector('#output')6
7 let count = 08
9 function onToggle() {5 collapsed lines
10 output.textContent = ++count11 }12
13 document.addEventListener('toggle', onToggle)14</script>
以下示例模拟了上述行为:
是的,我们实际上是使用了 dispatchEvent 加上 CustomEvent 来完成了自定义事件触发的过程,使用原生的 addEventListener
来完成添加观察者的行为。
使用原生方案实现的一个好处是不需要引入额外的库,不会增加项目体积,同时还兼容各种框架,但缺点是需要手动维护事件,并且只能在非SSR的情况下使用,除此之外,CustomEvent
在 IE 上使用也会有兼容性问题(万恶的IE)。
触发其他组件按钮中的方法
其实平时在框架开发中,偶尔也会遇到调用其他组件的方法,比如说A组件内的一个按钮点击以后需要触发和B组件中某个按钮点击以后执行的事件,我们就可以利用 HTML 中 <label />
元素的 for
属性与目标按钮的 id
属性绑定:
1<!-- 组件A -->2<label for="button">3 <!-- 需要注意的是,如果这里面不能使用 button 标签,否则 for 属性则会失效 -->4 <!-- 因为 label 默认会找最近的表单元素进行关联,如果内部有表单则不会使用 for 去寻找外部表单 -->5 <!-- 同时 组件B 中与 label 所关联的元素也需要是 <button /> 或 <input /> -->6 <span>组件A的按钮</span>7</label>
1<!-- 组件B -->2<button id="button" onclick="javascript:alert(1);">组件B的组件</button>
以下示例模拟了上述行为:
以上。