Возможно, есть более элегантный способ сделать это, но один из вариантов - сначала удалить элемент из DOM, отправить ему событие, а затем поместить его обратно в DOM:
document.body.addEventListener('keydown', () => {
console.log('body keydown capturing');
}, true);
document.body.addEventListener('keydown', () => {
console.log('body keydown bubbling');
});
const input = document.querySelector('input');
input.addEventListener('keydown', () => {
console.log('input keydown');
});
const node = document.createTextNode('');
input.replaceWith(node);
input.dispatchEvent(new Event('keydown'));
node.replaceWith(input);
<input>
Поскольку элемент не находится в DOM при отправке события, элементы, которые использовали в качестве своих предков, не будут см. событие.
Обратите внимание, что события, отправленные отсоединенным элементам , не захватывают / не всплывают независимо от , даже от родителей или дочерних элементов элемента, которому было отправлено событие.
Не удаляя элемент из DOM полностью заранее, если вход может существовать в теневом DOM, вы также можете отправить туда событие, и событие не будет записываться или всплывать (хотя пользовательский ввод не является пользовательским событием). , будет распространяться через):
document.body.addEventListener('keydown', () => {
console.log('body keydown capturing');
}, true);
document.body.addEventListener('keydown', () => {
console.log('body keydown bubbling');
});
outer.attachShadow({mode: 'open'});
const input = document.createElement('input');
outer.shadowRoot.append(input);
input.addEventListener('keydown', () => {
console.log('input keydown');
});
input.dispatchEvent(new Event('keydown'));
<div id="outer"></div>
Другой подход заключается в вызове stopPropagation
и stopImmediatePropagation
в фазе захвата в самом начале, когда событие находится на window
, а затем вручную вызвать функцию прослушивания, которую вы хотите. Обязательно подключите ваш оконный прослушиватель перед запуском любых других сценариев на странице, чтобы убедиться, что никто из слушателей страницы не сможет увидеть событие первым:
// Your script:
const input = document.body.appendChild(document.createElement('input'));
input.className = 'custom-extension-element';
const handler = (e) => {
setTimeout(() => {
console.log(e.target.value);
});
};
window.addEventListener(
'keydown',
(e) => {
if (e.target.closest('.custom-extension-element')) {
e.stopImmediatePropagation(); // Stop other capturing listeners on window from seeing event
e.stopPropagation(); // Stop all other listeners
handler(e);
}
},
true // add listener in capturing phase
);
// Example page script
// which tries to attach listener to window in capturing phase:
window.addEventListener(
'keydown',
(e) => {
console.log('page sees keydown');
},
true
);
document.body.addEventListener('keydown', () => {
console.log('body keydown capturing');
}, true);
document.body.addEventListener('keydown', () => {
console.log('body keydown bubbling');
});