【问题标题】:Is there a way of accessing HTML tag attribute in CSS within Shadow-DOM?有没有办法在 Shadow-DOM 中访问 CSS 中的 HTML 标签属性?
【发布时间】:2021-05-10 08:25:52
【问题描述】:

我正在使用 StencilJS 创建一个自定义组件,当用户使用键盘或鼠标导航到组件时,我必须对大纲进行一些更改。

我的组件正在使用 ShadowDOM,我想从 CSS 访问 HTML 标记属性。

标签的属性由what-input (https://github.com/ten1seven/what-input) 生成,用于检测键盘和鼠标事件。

我尝试过使用 [data-whatintent=keyboard]html[data-whatintent=keyboard] 等 CSS 选择器,但没有成功。

这是我要从中访问data-whatintent 属性的 HTML 标记:

<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;
}

我希望我在 ShadowDOM 中的 CSS 可以使用 data-whatintent 属性的值在我的组件上设置样式,以便轮廓符合我的要求。

【问题讨论】:

  • 您可以轻松地从组件访问它,例如document.querySelector('html').getAttribute('data-whatintent'),但是将属性值应用于样式是另一个问题。您到底需要对价值做什么?您是否事先知道有限数量的可能值?
  • 只有2个可能的值:键盘或鼠标,但我只希望CSS在值为keyboard时生效。

标签: html css typescript shadow-dom stenciljs


【解决方案1】:

您应该使用 :host-context() 在 Shadow DOM 中应用 CSS 样式,具体取决于使用自定义元素的上下文。

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>

【讨论】:

  • 无法使用 Stencil。我无权访问attachShadow()
  • @vincino 但你可以为你的组件定义 CSS 没有?
【解决方案2】:

Supersharp 的回答是正确的,但它不是 StencilJS 代码,而且主机上下文支持也很不稳定(在 Firefox 和可能 IE11 中不起作用)。

您可以将属性“转移”到宿主元素,然后使用宿主组件样式中的选择器:

多伦多证券交易所:

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 属性动态变化,请将其设为组件的属性,并让侦听器函数更新您的组件。您可以选择使用该属性向主机添加/删除类以进行样式设置,但您也可以继续使用属性选择器。

多伦多证券交易所:

@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)
    );
}

【讨论】:

  • 这样,intent 将始终具有相同的值?每次用户移动鼠标或按键时,data-whatintent 的值都会更新。
  • 如果是这样的用例,那么处理鼠标和键盘使用的任何侦听器都应该触发组件可以侦听的事件并更新“intent”值。无论如何都是一种可能的方法。
  • 我的 CSS 没有更新,但我的组件正在重新渲染,intent 已正确更新...
  • 我添加了一个动态更新的例子。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-19
  • 2022-08-02
  • 1970-01-01
  • 1970-01-01
  • 2022-09-22
  • 2017-08-09
相关资源
最近更新 更多