在 JavaScript 中,除了用户操作触发事件外,也可以通过 Element.dispatchEvent
去触发一个事件。举例来说,对于点击事件,除了用户触发外,也可以通过下面的代码触发:
const button = document.createElement('button');
button.addEventListener('click', (event) => {
console.log('clicked: ', event);
});
button.textContent = 'Click Me';
document.body.appendChild(button);
button.dispatchEvent(new MouseEvent('click'));
其中,点击事件更为特殊一些,还可以通过 Element 上本身自带的 .click
方法触发:
button.click();
那么,如何可以从代码层面区分,一次事件到底是用户触发的,还是程序触发的呢?
JavaScript 的 Event 中提供了一个 isTrusted
只读属性,用于标记当前的属性是否是由用户触发的。如果是,那么 isTrusted
就是 true
,否则都是 false
。这里无论是 dispatchEvent
还是直接调用 .click
方法,结果都是一样的(false
)。
同时,因为 isTrusted
属性是只读属性,因此想要进行修改也是不会成功的:
const event = new MouseEvent('click');
console.log(event.isTrusted); // => false
event.isTrusted = true;
console.log(event.isTrusted); // => false;
而如果试图通过 Proxy 去包装 Event,最终虽然可以拿到 isTrusted=true
,但是却无法被 dispatchEvent
认可:
const event = new MouseEvent('click');
const proxy = new Proxy(event, {
get(target, prop, receiver) {
if (prop === 'isTrusted') return true;
return Reflect.get(target, prop);
},
});
console.log(proxy.isTrusted); // => true
console.log(proxy instanceof MouseEvent) // => true
console.log(proxy.constructor) // => MouseEvent
// Error: Failed to execute 'dispatchEvent' on 'EventTarget':
// parameter 1 is not of type 'Event'.
document.body.dispatchEvent(proxy);
// Success
document.body.dispatchEvent(event);