javascript - Web 组件可以处理 CSS(cssChangedCallback 吗?)

标签 javascript css web-component

有什么方法可以像使用 attributeChangedCallback 处理属性一样处理 CSS 应用于 Web 组件的方式吗? .

我正在开发几个 Web 组件,这些组件将受益于使用 CSS 类设置样式,但我需要更改多种样式以使其看起来正确(例如,如果您设置控件的颜色,用户会期望边框一个元素的颜色和另一个元素的字体颜色在阴影 DOM 中改变)。


有什么方法可以得到 .usingCSS { color: red; } 更改以下简单 Web 组件示例中切换开关的颜色?

// based on https://www.w3schools.com/howto/howto_css_switch.asp

class W3schoolsToggleSwitch extends HTMLElement {
  constructor() {
    super();
    var shadow = this.attachShadow({ mode: "open" });
    this.span = document.createElement("span");
    this.span.innerHTML = `
    <style>
      /* The switch - the box around the slider */
      .switch {
        --color: #2196F3;
        position: relative;
        display: inline-block;
        width: 60px;
        height: 34px;
      }

      /* Hide default HTML checkbox */
      .switch input {
        opacity: 0;
        width: 0;
        height: 0;
      }

      /* The slider */
      .slider {
        position: absolute;
        cursor: pointer;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background-color: #ccc;
        -webkit-transition: .4s;
        transition: .4s;
      }

      .slider:before {
        position: absolute;
        content: "";
        height: 26px;
        width: 26px;
        left: 4px;
        bottom: 4px;
        background-color: white;
        -webkit-transition: .4s;
        transition: .4s;
      }

      input:checked + .slider {
        background-color: var(--color);
      }

      input:focus + .slider {
        box-shadow: 0 0 1px #2196F3;
      }

      input:checked + .slider:before {
        -webkit-transform: translateX(26px);
        -ms-transform: translateX(26px);
        transform: translateX(26px);
      }

      /* Rounded sliders */
      .slider.round {
        border-radius: 34px;
      }

      .slider.round:before {
        border-radius: 50%;
      }
    </style>
    <label class="switch">
        <input type="checkbox" checked>
        <span class="slider round"></span>
    </label>
    `;
    shadow.appendChild(this.span);
  }

  static get observedAttributes() {
    return ["color"];
  }

  attributeChangedCallback(name, oldValue, newValue) {
    console.log(name, newValue);
    if ("color" === name) {
      this.shadowRoot
        .querySelector(".switch")
        .style.setProperty("--color", newValue);
    }
  }

  get color() {
    return this.getAttribute("color");
  }

  set color(value) {
    return this.setAttribute("color", value);
  }
}

customElements.define("w3schools-toggle-switch", W3schoolsToggleSwitch);
.usingCSS {
  color: red;
}
default:
<w3schools-toggle-switch></w3schools-toggle-switch>

<br><br> color attribute used to change the color to green:
<w3schools-toggle-switch color="green"></w3schools-toggle-switch>

<br><br> can you change the color with CSS?:
<w3schools-toggle-switch class="usingCSS"></w3schools-toggle-switch>

最佳答案

从外面用 <链接 >

您可以使用 <link> 将 CSS 样式应用于 Web 组件Shadow DOM 中的元素。

#shadow-root
  <link rel="stylesheet" href="default.css">

attributeChangedCallback( name, old, value ) {
   if (name === 'class') 
      this.shadowRoot.querySelector( 'link' ).href = value + ".css"

} 

在 Shadow DOM 中定义样式 :host()伪类函数

您可以根据上下文应用不同的样式。您可以组合多个类。

customElements.define( 'custom-element', class extends HTMLElement {
  constructor() {
    super()
    this.attachShadow( { mode: 'open' } )
        .innerHTML = `
          <style>
            :host( .red ) { color: red }
            :host( .blue ) { color: blue }
            :host( .border ) { border: 1px solid }
          </style>
          Hello`
  }
} )

ce1.onclick = ev => ev.target.classList.add( 'border' )
<custom-element class="red" id="ce1"></custom-element>
<custom-element class="blue border"></custom-element>

在 Chrome/Opera 上:使用 Constructable stylesheets

创建一个(或多个)样式表并将其应用到 Shadow DOM。您可以将多个样式表应用于同一个 Shadow DOM。

var ss = []
ss['red'] = new CSSStyleSheet
ss.red.replaceSync( 'span { color: red }' ) 
ss['green'] = new CSSStyleSheet
ss.green.replaceSync( 'span { color: green }' ) 
ss['border'] = new CSSStyleSheet
ss.border.replaceSync( 'span { border: 1px solid }' ) 

customElements.define( 'custom-element', class extends HTMLElement {
  constructor() {
    super()
    this.attachShadow( { mode: 'open' } )
        .innerHTML = `<span>Hello</span>`
  }
  
  static get observedAttributes() { return [ 'class' ] }
  
  attributeChangedCallback() {
    this.shadowRoot.adoptedStyleSheets = [ ...this.classList ].map( cl => ss[ cl ] )
  }
} )

ce1.onclick = ev => ev.target.classList.add( 'border' )
<custom-element class="red" id="ce1"></custom-element>
<custom-element class="green border"></custom-element>

关于javascript - Web 组件可以处理 CSS(cssChangedCallback 吗?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58921620/

相关文章:

javascript - JQuery 滑动开关 :visible conditional

javascript - webcomponents - 隐藏 window.onclick 上的下拉菜单

javascript - 如何在 Angular.js 的 ng 类中使用包含破折号的类?

javascript - React : on hover over component 1, 改变另一个组件的样式

javascript - 如何在 Javascript/Jquery 中以编程方式调用突出显示效果(类似于鼠标悬停)?

JavaScript while 循环失败

angular - 如何延迟组件实例化,直到在 Angular 2 中收到来自服务的数据?

javascript - 如何判断是否加载了 polymer 元件?

javascript - 在页面向下滚动时将 pageYOffset 值添加到 div 的位置

javascript - PyQT4 Javascript 警报