dispatchEvent模拟事件的使用场景

模拟事件

事件是为了表示网页中某个有意义的时刻。通常,事件都是由用户交互或浏览器功能触发。事实 上,可能很少有人知道可以通过JavaScript在任何时候触发任意事件,这些事件会被当成浏览器创建的事件,他们同样会有事件冒泡,因而也会触发相应的事件处理程序。

我们将非用户触发的事件称之为"模拟事件",通过调用event.isTrusted我们可以查看一个事件是否是模拟事件。isTrusted是一个表示事件是否由用户行为生成的布尔值,当事件由用户行为触发时,为 true,当事件由脚本创建或修改,或通过 EventTarget.dispatchEvent()派发时,为 false

第一个例子

任何时候,都可以使用 new Event 创建一个自定义的事件实例对象,然后通过dispatchEvent来触发这个模拟事件,通过下面这段代码我们就可以在不点击按钮的情况下触发click事件。

csharp 复制代码
let btn = document.getElementById("myBtn"); 

var event = new Event("click", { bubbles: true, cancelable: false }); // 创建 event 对象 

btn.dispatchEvent(event); // 触发事件 

进一步思考使用场景

假设有一项事件,是需要在我们提交表单之后,向某个顶层父组件通知 "子组件已经完成表单提交了!",并传递某些特定的信息上去,常规思路自然是一层一层由子组件emit上去,这种情况下,在子组件提交表单之后,自定义一个"submited"事件,然后由document去触发,同时在父组件中用 addEventListener 监听"submited",就可以避免一层层传值的窘境。

javascript 复制代码
子组件
const submited = () => { 
    document.dispatchEvent(new Event('submited')) 
}

父组件
document.addEventListener('submited', (event) => { console.log('event', event) })
  

但这样写这段代码,实际并不会生效,上面代码中,发出的submited事件在没有设置属性的情况下默认不会冒泡,而addEventListener方法在不设置第三个参数的情况下又默认在冒泡阶段监听,因此监听函数不会触发。

我们将代码稍作修改,设置事件属性为冒泡,且不可以被取消,那么即使调用Event.preventDefault()也不可以取消这个事件。

javascript 复制代码
子组件
const submited = () => { 
    document.dispatchEvent(new Event('submited', { 
        'bubbles': true, 
        'cancelable': false
    })) 
}

父组件
document.addEventListener('submited', (event) => { console.log('event', event) })
  

升级场景

例如,假设有一个购物车组件和一个订单结算组件。当购物车中的商品发生变化时,可以触发一个名为 cartUpdated 的自定义事件,订单结算组件通过监听这个事件来更新结算信息

javascript 复制代码
// 创建自定义事件
const cartUpdatedEvent = new Event('cartUpdated',{ 
        'bubbles': true, 
        'cancelable': false
    });

// 购物车组件中触发事件
document.dispatchEvent(cartUpdatedEvent);

// 订单结算组件中监听事件
document.addEventListener('cartUpdated', () => {
  // 更新结算信息的逻辑
});

再例如,为了避免click在移动端300ms的延迟,想要将页面所有click事件全部替换为tap事件

csharp 复制代码
// 监听所有的 click 事件
    document.addEventListener('click', function(event) {
      // 创建一个新的自定义事件 tap
      const tapEvent = new Event('tap', { 
        'bubbles': true, 
        'cancelable': false
    });

      // 复制原始 click 事件的相关属性到 tap 事件
      tapEvent.clientX = event.clientX;
      tapEvent.clientY = event.clientY;
      tapEvent.screenX = event.screenX;
      tapEvent.screenY = event.screenY;

      // 触发 tap 事件
      event.target.dispatchEvent(tapEvent);
    });

    // 监听 tap 事件
    document.addEventListener('tap', function(event) {
      console.log('tap 事件被触发',event);
    }
相关推荐
DokiDoki之父3 分钟前
前端速通—CSS篇
前端·css
pixle06 分钟前
Web大屏适配终极方案:vw/vh + flex + clamp() 完美组合
前端·大屏适配·vw/vh·clamp·终极方案·web大屏
ssf198712 分钟前
前后端分离项目前端页面开发远程调试代理解决跨域问题方法
前端
@PHARAOH12 分钟前
WHAT - 前端性能指标(加载性能指标)
前端
尘世中一位迷途小书童17 分钟前
🎨 SCSS 高级用法完全指南:从入门到精通
前端·css·开源
非凡ghost22 分钟前
火狐浏览器(Firefox)tete009 Firefox 多语便携版
前端·firefox
文心快码BaiduComate22 分钟前
文心快码Comate3.5S更新,用多智能体协同做个健康管理应用
前端·人工智能·后端
袁煦丞26 分钟前
极空间变身全能私有云+1Panel傻瓜式部署:cpolar内网穿透实验室第618个成功挑战
前端·程序员·远程工作
袁煦丞29 分钟前
10.15-1 Reader电子书管理神器搭配极空间私有云:cpolar内网穿透实验室第488个成功挑战
前端·程序员·远程工作
ZHOUYUANN1 小时前
我用JavaScript复刻了某宝的小游戏动物大迁徙消消乐
前端·javascript·游戏开发