Слушатель событий вне Shadow DOM не будет связываться с элементами внутри Shadow DOM - PullRequest
3 голосов
/ 16 апреля 2019

У меня на сайте установлен веб-компонент Angular. Он использует Shadow DOM, поэтому он очень быстрый (что и должно быть в моем случае).

На моем сайте у меня также есть ярлык на h , который открывает всплывающее окно, отображающее некоторую полезную информацию. Обязательно, чтобы эта h оставалась без изменений. Пример кода того, как это было реализовано, можно увидеть здесь: https://jsfiddle.net/js1edv37/

Это простой прослушиватель событий, который прослушивает document:

$(document).on("keyup", function(e) {

}

Однако это также срабатывает, когда мой веб-компонент имеет фокусированные элементы textarea или input. Это происходит потому, что он использует Shadow DOM, к которому скрипт извне не может получить доступ.

Вы можете проверить это, нажав h на клавиатуре внутри и снаружи элементов input и textarea.

Есть ли способ разрешить моему скрипту извне веб-компонента Shadow DOM по-прежнему прослушивать событие keyup, но заставить его прослушивать всех элементов на странице? Даже те, что находятся в Shadow DOM.

Ответы [ 2 ]

3 голосов
/ 16 апреля 2019

В веб-компоненте получите элемент input с помощью вызова querySelector() для свойства shadowRoot:

let textareainshadow = div.shadowRoot.querySelector( 'textarea' )

Затем прослушайте событие keyup и остановите его распространение с помощью метода stopImmediatePropagation().

textareainshadow.addEventListener( 'keyup' , ev => {
    console.log( 'caught', ev.type )
    ev.stopImmediatePropagation()
}) 

https://jsfiddle.net/7mkrxh25/1/

2 голосов
/ 16 апреля 2019

Если вы сохраните ссылку на теневой корень, вы всегда сможете получить доступ к его дочерним элементам при поиске по этим

$(document).on("keyup", function(e) {
    let focusedInputs = $("input:focus, textarea:focus").length + $(shadow).children("input:focus, textarea:focus").length;

    if (focusedInputs > 0) {
        return true;
    }

    if (e.keyCode === 72) {
        trigger();
    }
});

function trigger() {
    alert("If this was triggered, everything is perfectly fine");
}

let div = document.querySelector("div");
let shadow = div.createShadowRoot();
shadow.innerHTML = "<textarea>This shouldn't fail</textarea>";
textarea {
    width: 500px;
    height: 100px;
}

input {
    width: 250px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<textarea>Some stuff here</textarea>
<br />
<input type="text" value="Some more text here" />

<br />
<br />

<h1>Shadow DOM element WON'T fail now :)</h1>

<div></div>

Fiddle

...