#html #css #typescript #shadow-dom #stenciljs
#HTML #css #typescript #shadow-dom #stenciljs
Вопрос:
Я создаю пользовательский компонент с помощью StencilJS, и мне нужно внести некоторые изменения в контур, когда пользователь использует клавиатуру или мышь для перехода к компоненту.
Мой компонент использует ShadowDOM, и я хочу получить доступ к атрибуту HTML-тега из CSS.
Атрибуты тега генерируются с помощью what-input (https://github.com/ten1seven/what-input ) для обнаружения событий клавиатуры и мыши.
Я пробовал использовать CSS-селекторы, такие как [data-whatintent=keyboard]
и html[data-whatintent=keyboard]
, но это не сработало.
Это мой HTML-тег, из которого я хочу получить доступ к data-whatintent
атрибуту:
<html dir="ltr" lang="en" data-whatinput="keyboard" data-whatintent="mouse">
<my-custom-component></my-custom-component>
</html>
И это мой CSS:
[data-whatintent=keyboard] *:focus {
outline: solid 2px #1A79C6;
}
Я хочу, чтобы мой CSS в ShadowDOM мог использовать значение data-whatintent
атрибута для установки стилей в моем компоненте, чтобы контур был таким, как я хочу.
Комментарии:
1. Вы можете легко получить к нему доступ из компонента, например,
document.querySelector('html').getAttribute('data-whatintent')
, но применение значения атрибута к стилю — это совсем другой вопрос. Что именно вам нужно сделать со значением? Существует ли конечное число возможных значений, которые вы знаете заранее?2. Только 2 возможных значения: клавиатура или мышь, но я хочу, чтобы CSS действовал только тогда, когда значение равно
keyboard
.
Ответ №1:
Ответ Supersharp правильный, однако это не код StencilJS, а также поддержка контекста хоста ненадежна (не работает в Firefox и, вероятно, IE11).
Вы можете «перенести» атрибут в элемент host, а затем использовать селектор из стиля компонента host:
TSX:
private intent: String;
componentWillLoad() {
this.intent = document.querySelector('html').getAttribute('data-whatintent');
}
hostData() {
return {
'data-whatintent': this.intent
};
}
SCSS:
:host([data-whatintent="keyboard"]) *:focus {
outline: solid 2px #1A79C6;
}
Если data-whatintent
атрибут изменяется динамически, сделайте его свойством компонента и попросите функцию прослушивания обновить ваш компонент. При желании вы можете использовать свойство для добавления / удаления классов на хост для стилизации, хотя вы также могли бы продолжать использовать селектор атрибутов.
TSX:
@Prop({ mutable: true, reflectToAtrr: true }) dataWhatintent: String;
componentWillLoad() {
this.dataWhatintent = document.querySelector('html').getAttribute('data-whatintent');
}
hostData() {
return {
class: {
'data-intent-keyboard': this.dataWhatintent === 'keyboard'
}
};
}
SCSS:
:host(.data-intent-keyboard) *:focus {
outline: solid 2px #1A79C6;
}
Обработчик событий клавиатуры и мыши документа:
function intentHandler(event: Event) {
const intent = event instanceof KeyboardEvent ? 'keyboard' : 'mouse';
document.querySelectorAll('my-custom-component').forEach(
el => el.setAttribute('data-whatintent', intent)
);
}
Комментарии:
1. При этом
intent
всегда будет иметь одно и то же значение? Значениеdata-whatintent
обновляется каждый раз, когда пользователь перемещает мышь или нажимает клавишу.2. Если это вариант использования, то любой прослушиватель, обрабатывающий использование мыши и клавиатуры, должен запустить событие, которое компонент может прослушать и обновить значение «intent». В любом случае, один из возможных подходов.
3. Мой CSS не обновлялся, но мой компонент повторно визуализируется и
intent
обновляется правильно…4. Я добавил пример для динамического обновления.
Ответ №2:
Вы могли бы использовать:host-context() для применения стиля CSS в Shadow DOM в зависимости от контекста, в котором используется пользовательский элемент.
customElements.define( 'my-custom-component', class extends HTMLElement {
constructor() {
super()
this.attachShadow( { mode: 'open' } )
.innerHTML = `
<style>
:host-context( [data-whatinput=keyboard] ) *:focus {
outline: solid 2px #1A79C6;
}
</style>
<input value="Hello">`
}
} )
<html dir="ltr" lang="en" data-whatinput="keyboard" data-whatintent="mouse">
<my-custom-component></my-custom-component>
</html>
Комментарии:
1. Это не сработало с использованием Stencil. У меня не было доступа к
attachShadow()
.2. @vincino но вы можете определить CSS для своего компонента no?