Как мы наблюдаем изменения распределения в теневом корне v0?

В теневых корнях v1 мы можем прослушивать slotchange на <slot> элементах, а затем использовать slot.assignedNodes() для обнаружения изменений. Я ищу способ сделать это с теневыми корнями v0.

Есть ли в ShadowDOM v0 способ наблюдать за изменениями в распределенных узлах элемента <content> в теневом корне?

Самый простой способ реализовать это — использовать requestAnimationFrame для создания цикла опроса, который вызывает content.getDistributedNodes() для сравнения новых результатов со старыми, но очевидно, что опрос не идеален и дорог.

Как это сделать?


person trusktr    schedule 30.11.2016    source источник
comment
Не могли бы вы использовать наблюдатель мутаций для элемента content?   -  person KevBot    schedule 30.11.2016
comment
@KevBot Как бы я это сделал? childList наблюдает за потомками, а как насчет распределенных узлов? Есть пример?   -  person trusktr    schedule 30.11.2016
comment
Это возможно с помощью метода .getDistributedNodes() и из там для этих элементов можно вызвать наблюдателя мутаций. Или, возможно, прикрепить наблюдателя мутаций к точкам вставки .getDestinationInsertionPoints(). Утром постараюсь придумать что-нибудь более конкретное.   -  person KevBot    schedule 30.11.2016
comment
Какой-нибудь контекст, почему за это проголосовали?   -  person KevBot    schedule 30.11.2016
comment
@KevBot, я немного подумал об этом: для данного элемента контента, который мы хотим наблюдать, мы можем перейти от него, чтобы найти теневой корневой хост, а затем использовать MutationObserver на хосте для обнаружения изменений в дочерних элементах и ​​всякий раз, когда это происходит мы просто вызываем .getDistributedNodes для элемента содержимого, чтобы найти новое распределение. Нам также потребуется использовать MutationObserver на всех дочерних элементах хоста для обнаружения изменений атрибутов, поскольку они могут привести к изменению результатов селектора корневого элемента <content>.   -  person trusktr    schedule 02.12.2016
comment
Также любопытно узнать, почему заминусовали.   -  person trusktr    schedule 02.12.2016
comment
Нужно ли отслеживать изменения текстовых узлов (characterData) в наблюдателе мутаций? Или вы просто ищете изменения атрибутов, а также добавление или удаление узлов?   -  person KevBot    schedule 02.12.2016
comment
Да, текстовые узлы могут быть распределены по элементу содержимого по умолчанию, если у элемента содержимого нет селектора. Но если есть селектор, то в этом случае текстовые узлы не могут быть выбраны.   -  person trusktr    schedule 02.12.2016


Ответы (1)


У меня была потребность в этой точной вещи примерно в то же время, что и у вас. В итоге я создал библиотеку для этого, которую я использую уже неделю или около того при тестировании. Библиотека называется content-change. Это работает хорошо для меня, но я уверен, что есть много возможностей для улучшения.

Это работает так; аналогично событию slotchange элемента slot из Shadow DOM v1:

// Because this is non-spec, specify internally which components get to be watched
// "this" is the host element
ContentChange.watch(this);

const contentElement = shadow.querySelector('someContentSelector');
contentElement.addEventListener('contentchange', e => {
    // React to distributed node changes for this content element
});

event, возвращаемый слушателю, содержит несколько разных типов в event.details. event.details.type будет одним из трех:

  • "nodesAdded"
  • "nodesRemoved"
  • "mutation"

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

{
    "type": "nodesAdded",
    "nodesAdded": [Nodes] // An array of newly distributed nodes
}
person KevBot    schedule 21.12.2016
comment
Прохладный! Хорошая реализация. Я тоже думал об этом, используя MutationObserver на хосте, но затем для части моей реализации, которая была бы эквивалентна вашему discoverAddedAndRemovedNodes, я думал запустить запрос, связанный с элементами <content>, чтобы узнать, какие элементы в хосте совпадают, но ваш подход с использованием getDistributedNodes просто чище. То есть вы используете getDistributedNodes для изменений MutationObserver, в отличие от моего исходного поста, где я думал об использовании getDistributedNodes внутри цикла опроса кадра анимации. - person trusktr; 21.12.2016
comment
Кстати, есть мысли по следующему вопросу? stackoverflow.com/questions/40004064 Я думаю, что это было бы хорошо, потому что я хотел бы наблюдать за изменениями распределения на хосте, но я я не создаю хосты, поэтому я не знаю, используют ли они слоты v0 или v1. Как только я обнаружу это, я смогу использовать вашу библиотеку изменения содержимого в корнях v0. :D - person trusktr; 21.12.2016
comment
@trusktr Да, на самом деле я пошел по пути, пытаясь выяснить, какие элементы могут распространяться с хоста со всеми правилами из элементов контента. Но в итоге получилось так, что если элемент контента не использует селектор или имеет * в качестве селектора, то он распределяет текстовые узлы (как вы уже знаете). С этими текстовыми узлами было действительно сложно работать. В любом случае, я посмотрю на этот другой вопрос, выглядит очень интересно. - person KevBot; 22.12.2016
comment
Спасибо за этот другой ответ. Работает потрясающе. Я собираюсь попробовать вашу библиотеку в ближайшее время. :D - person trusktr; 01.01.2017
comment
@trusktr, пожалуйста. Рад, что это сработало для вас. - person KevBot; 06.01.2017