Отправка события на элемент в обход захвата и всплытия - PullRequest
1 голос
/ 24 апреля 2020

Поскольку dispatchEvent в соответствии с документами , будут применяться:

нормальные правила обработки событий (включая фазу захвата и необязательный всплеск)

Я ищу что-то похожее, но с возможностью пропустить этот процесс и вызвать событие непосредственно на элементе. Чтобы запустить поведение события элемента по умолчанию, минуя этап обработки.

Например, захватить событие на уровне window (до того, как оно достигнет других триггеров захвата) и передать его непосредственно компоненту (текстовая область ) вызывая его напрямую.

(Например, для запуска нажатия по умолчанию текстовой области без прохождения иерархии)

Я пытался сделать это так, но если есть другой событие на уровне окна это не будет работать:

window.addEventListener("keydown", this.keyDown, true);

keyDown = (event) => {
      event.preventDefault();
      event.nativeEvent && event.nativeEvent.stopImmediatePropagation();
      event.stopImmediatePropagation && event.stopImmediatePropagation();
      event.stopPropagation();

      // Pass event straight to the element

      return false;
  };

Я ищу, чтобы вызвать поведение события элемента по умолчанию в обход обработки

Ответы [ 2 ]

1 голос
/ 24 апреля 2020

Возможно, есть более элегантный способ сделать это, но один из вариантов - сначала удалить элемент из 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');
});
0 голосов
/ 24 апреля 2020

Лучший способ обойти проблемы распространения - просто выполнить функцию:

function tester(){
  console.log("Just fire the function! Don't dispatchEvent!");
}
tester();
document.getElementById('test').onkeyup = function(e){
  e.stopPropagation();
  console.log(this.id); console.log(e.target); tester();
}
document.body.onkeyup = ()=>{
  console.log("This shouldn't fire when on #test");
}
<input id='test' type='text' value='' />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...