以上示例代码将事件监听器对象限制为 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 }10
2 collapsed lines
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() {10 output.textContent = ++count4 collapsed lines
11 }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>
以下示例模拟了上述行为:
以上。