为什么我的 Web 组件中的文本样式不使用我添加到 shadowroot 的外部样式表?

Why isn't text styling in my web component using the external stylesheet I added to the shadowroot?

我正在使用来自外部 CDN 的 Bulma css 库,并且正在尝试构建导航栏 Web 组件。出于某种原因,我的菜单项的文本显示为 Times New Roman 而不是 sans-serif。它应该继承 Bulma 的默认字体系列,但似乎使用的是浏览器默认值。

我是否需要将每个子项目附加到 shadowRoot 以继承缅甸的文本样式或类似的样式?

这里是 html (index.html):

<!DOCTYPE html>
<html lang="en">
<head>
    <title>hello</title>
    <meta charset="utf-8">
</head>
<body>   
    <my-element></my-element>

    <script src="./js/index.js" type="module"></script>

</body>
</html>

这是我的主要 javascript 文件 (index.js):

import { MyElement } from './components/header.js';

if(!customElements.get('my-element')){
    customElements.define('my-element', MyElement)
}

这是我的网络组件代码 (header.js):

export class MyElement extends HTMLElement {
    constructor() {

        super()

        let count = Math.floor(Math.round() * 10) + 1
        let items = ["Home", "Config", "Admin"]

        let that = this
        let id = Math.random()
        this.id = id

        // and use it in the constructor after creating the shadow DOM
        
        this.attachShadow({ mode: 'open' })
        this.shadowRoot.innerHTML = `<link rel=stylesheet  href='https://cdn.jsdelivr.net/npm/bulma@0.9.2/css/bulma.min.css'>`


        // main header element
        let header = document.createElement('nav')
        header.classList.add('navbar')
        header.id = 'header'
        header.role = 'navigation'

        // brand container
        let brand = document.createElement('div')
        brand.classList.add('navbar-brand')

        let brandImg = document.createElement('img')
        brandImg.src = 'https://www.zilliondesigns.com/images/how-to/swoosh-concepts-02.png'
        brandImg.width = '100'
        
        // menu container
        let menu = document.createElement('div')
        menu.classList = 'navbar-menu'
        menu.id = 'navbarexample'

        let menuLeft = document.createElement('div')
        menuLeft.classList = 'navbar-start'

        // menu items
        items.forEach(item => {
            let child = document.createElement('a')
            child.classList='navbar-item'

            child.innerText = item
    
            menuLeft.appendChild(child)  
            child.addEventListener('click', e => {
                e.target
                child.remove()
            })
        })

        menu.appendChild(menuLeft)

        brand.appendChild(brandImg)
        header.appendChild(brand)
        header.appendChild(menu)

        this.shadowRoot.appendChild(header)



    }
}

HTML 中的 shadowRoot 由 Burma 设计,无所谓 如何 添加 HTML

(顺便说一句..你的许多 appendChilds 可以用一个 append 代替)

<my-element></my-element>
<script>
  if (!customElements.get('my-element')) {
    customElements.define('my-element', class extends HTMLElement {
      constructor() {
        super()
          .attachShadow({mode: 'open'})
          .innerHTML = `<link rel=stylesheet  href='https://cdn.jsdelivr.net/npm/bulma@0.9.2/css/bulma.min.css'>` +
          `<div class="button is-large">This is a Bulma styled button</div>`;
      }
    });
  }
</script>

您看到默认用户代理字体的原因是 Bulma 显然没有考虑到影子根。

它为以下元素设置 font-family

body,
button,
input,
optgroup,
select,
textarea {
  font-family: BlinkMacSystemFont, -apple-system, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
}

因为您的 div.button.is-large 不是任何这些元素的后代,所以没有要继承的 Bulma 字体定义。我高度认为这也适用于其他常见的继承属性,如 color

要修复它,只需在主页上也包含 Bulma CSS:

<link rel=stylesheet href="https://cdn.jsdelivr.net/npm/bulma@0.9.2/css/bulma.min.css">

在继承方面,这将使影子根中的元素成为 body 元素的“后代”,从而再次继承继承的样式。

或者,我建议您创建一个带有静态 属性 stylesComponentStyles.js class,如下所示:

export class ComponentStyles {
   static get styles() {
       return `:host { font-family: BlinkMacSystemFont, -apple-system, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; }`;
   }
}

在您的组件中,导入它然后在构造函数中使用它:

import { ComponentStyles } from './path/to/ComponentStyles.js';

// ...

constructor() {
    // ...
    let style = document.createElement('style');
    style.textContent = ComponentStyles.styles;
    this.shadowRoot.appendChild(style);
    // ...
}