事件监听
- 标签中的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,注意这是区分大小写的,并且传递了自定义的对象。