事件监听

  • 标签中的onxxx,比如<button οnclick="btnHandler">按钮</button>
  • js中的onxxx,比如document.body.onclick = function() { /* body click */ }
  • js中的addEventListener,比如document.body.addEventListener("click", () => { /* body click */ })

这三种中最好的就是最后一种了,不仅便于管理,而且可以给一个元素的任意一个事件添加多个监听器。

手动触发事件(dispatchEvent)

示例1

我们有时候会需要通过js修改表单元素的状态, 因为不是通过页面交互而是js操作的, 所以不会触发我们写的监听事件.这时就需要通过js手动触发监听事件.

jquery实现方法就是trigger('eventType')

原生实现:

<input type="checkbox" id="chk">
document.querySelector('#chk').addEventListener('change', function() {
    console.log(this.checked);
    console.log('1111');
    // 执行其他逻辑处理
    
});

如果用户手动点击多选框,可以实现多选框的选中与取消选中, 并触发监听事件.

假如多选框默认为取消选中状态, 但是经过逻辑处理之后发现需要通过js将多选框选中, 所以执行以下方法

document.getElementById('chk').checked = true;

不要通过修改多选框的checked属性来标记多选框的选中状态, 那个属性只代表多选框的默认选中状态, 如果checked="checked"表明多选框默认选中, 否则默认不选中. 其他标签的checked, selected属性也一样都代表默认选中.

通过以上的执行, 虽然页面多选框被选中了, 但是监听事件并没有被触发, 监听事件回调的一些逻辑处理就没有执行, 这会造成一些错误.我们需要手动触发监听事件.

document.querySelector('#chk').dispatchEvent(new Event('change', {
    bubbles: false, // 默认值false, 事件是否冒泡
    cancelable: false,  // 默认值false, 事件能否被取消
    composed: false  // 默认值false, 事件是否会在影子DOM根节点之外触发侦听器。
}));

这样监听事件就会触发,并且打印true和1111.

更多事件可以参考基于Event的接口,都可以使用new构造函数的方式使用。

示例2

使用customEvent来触发自定义事件并传递额外的参数。

我们使用别人写的插件时,经常看到一些自定义的事件监听,这些事件监听和普通的事件监听没什么不同,只不过是在代码执行的不同阶段触发注册的监听回调而已。

<button class="btn1">按钮1</button>
<button class="btn2" data-index="1">按钮2</button>
const btn1 = document.querySelector(".btn1");
const btn2 = document.querySelector(".btn2");
btn1.addEventListener("click", () => {
  console.log("按钮1被点击了.");
});
btn2.addEventListener("click", (e) => {
  console.log("按钮2被点击了.");
  // 原生事件的detail表示短时间内事件触发的次数
  console.log("click detail:", e.detail);
});

const target = new EventTarget();
target.addEventListener("customEvent", (e) => {
  // 自定义事件的detail表示传递的自定义参数
  console.log("customEvent detail:", e.detail);
});
// 按钮1点击, 触发自定义对象的自定义事件 customEvent
btn1.addEventListener("click", () => {
  const params = {
    a: "a",
    b: "b",
  };
  target.dispatchEvent(
    new CustomEvent("customEvent", {
      detail: {
        index: btn2.dataset.index,
        ...params,
      },
    })
  );
});

如果直接双击btn2,detail就会打印1, 2触发事件的次数。如果慢慢点击只会打印1。

如果点击btn1,detail就会打印dispatchEvent函数中传递的detail对象。

先是快速双击btn2,然后慢慢点击两次 btn2,最后点击btn1,可以看到btn1的点击事件触发了自定义对象上绑定的自定义监听事件customEvent,注意这是区分大小写的,并且传递了自定义的对象。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐