У меня есть два веб-компонента на Lit-элементах - один units-list
, который содержит множество units-list-item
элементов. Элементы units-list-item
имеют два разных режима отображения: компактный и подробный. Поскольку элемент списка поддерживает бесконечную прокрутку (и, следовательно, может содержать несколько тысяч единиц), нам нужен любой механизм, который переключается между двумя режимами, чтобы быть как можно более быстрым.
Именно поэтому я подумал, что идеальным решением было бы используйте псевдоселектор :host-context()
в стилях для элемента units-list-item
, так как каждый элемент units-list-item
может переключаться между двумя режимами отображения, просто изменяя класс, примененный к предку (который будет в теневом DOM элемента units-list
).
Для уточнения приведена соответствующая разметка элемента units-list
. Обратите внимание, что классы «триггеров» применяются к элементу #list-contents
, который является частью шаблона units-list
.
<div id="list-contents" class="${showDetails ? 'detail-view table' : 'compact-view table'}">
${units.map(unit => html`<units-list-item .unit="${unit}"></units-list-item>`)}
</div>
Как видите, флаг showDetails
определяет, применяется ли класс "detail-view" или "compact-view" к div, содержащему все элементы units-list-item
. Эти классы определенно применяются правильно.
Вот полный метод рендеринга из элемента units-list-item
(ненужная разметка удалена):
render() {
const {unit} = this;
// the style token below injects the processed stylesheet contents into the template
return html`
${style}
<div class="row compact">
<!-- compact row markup here -->
</div>
<div class="row detail">
<!-- detail row markup here -->
</div>
`;
}
Затем у меня в units-list-item
есть следующее стили элемента (мы используем S CSS, поэтому однострочные комментарии не являются проблемой):
// This SHOULD hide the compact version of the row when the
// unit list has a "detail" class applied
:host-context(.detail-view) div.row.compact {
display: none !important;
}
// This SHOULD hide the detail version of the row when the
// unit list has a "compact" class applied
:host-context(.compact-view) div.row.detail {
display: none !important;
}
В моем понимании: host-context selector говорит, что это должно работать, но Chrome просто отображает обе версии строки каждый раз, а инструменты Chrome dev показывают, что селекторы никогда не совпадают ни с одной из строк.
Я знаю, что есть несколько альтернатив, которые будут работать, но это единственный, о котором я знаю, позволил бы всему списку модулей переключать режимы, изменяя один класс на родительском элементе. Любое другое решение, которое я рассмотрел, потребовало бы, по крайней мере, обновления атрибута класса для каждого элемента units-list-item
в списке. Я хотел бы избежать этого, если это возможно.
Конечно, моя главная задача - просто сделать эту работу, если это возможно, но мне также любопытно несколько вещей и я не могу найти какую-либо информацию о них. Два вопроса, на которые я не могу найти ответ:
- Когда
:host-context
используется внутри элемента, который сам является частью теневого DOM, учитывает ли он теневой DOM родительского элемента для быть "контекстом хоста", или он прыгает "полностью" в DOM документа? - Если это первый,
:host-context
будет переходить несколько теневых границ DOM? Скажем, у меня есть пользовательский элемент page
, который содержит пользовательский элемент list
, который сам содержит много пользовательских элементов item
. Если этот элемент item
имеет правило :host-context
, будет ли браузер сначала сканировать теневой DOM элемента list
, а затем, если ничего не соответствует, сканировать теневой DOM элемента page
и, если все еще ничего не найдено, затем отсканируйте основной документ DOM до тега <html>
?