开发中,还是会遇到须要引入内部CSS到Shadow DOM状况,那么如何解决呢?作者就最近遇到的状况给出如下几种计划。
一、@import
示例代码
const template = document.createElement('template');class WhatsUp extends HTMLElement { connectedCallback() { const shadowRoot = this.attachShadow({mode: 'open'}); shadowRoot.innderHTML = ` <style> @import "./index.css"; // 外围代码 </style> <div>Sup</div> ` }}window.customElements.define('whats-up', WhatsUp);
长处:此办法兼容性十分好,点击查看caniuse。
毛病:性能
二、::part
::part
CSS 伪元素示意在暗影树中任何匹配 part
属性的元素。
示例代码
HTML
<template id="whats-up"> <div part="sup">Sup</div> <div part="foo">Sup</div></template><whats-up></whats-up>
CSS
whats-up::part(sup) { /* 款式作用于 `sup` 局部 */}whats-up::part(foo) { /* 款式作用于 `foo` 局部 */}
长处:简洁明了
毛病:兼容性不太好,点击查看caniuse。
三、var
CSS自定义属性能够穿透到 Shadow DOM中!
示例代码
JS
const template = document.createElement('template');template.innerHTML = `<style>button { background: var(--background); color: var(--color); padding: var(--padding); font-size: var(--font-size); border: 0;}</style><div>Sup</div>`;
CSS
whats-up { --background: #1E88E5; --color: white; --padding: 2rem 4rem; --font-size: 1.5rem;}
长处:兼容性好
毛病:比拟局限,只能内部定几个,款式不能“自在翱翔”
四、通过属性传入
示例代码
JS
class Whatsup extends HTMLElement { static get observedAttributes() {return ['css']} constructor() { super(); } get css() { return this.getAttribute('css'); } set css(value) { if (value === null || value === false) { this.removeAttribute('css'); } else { this.setAttribute('css', value); } } connectedCallback() { const shadowRoot = this.attachShadow({ mode: 'open' }); shadowRoot.innerHTML = ` <style> :host{ display: flex; } ${this.css} // 外围代码 </style> <div class="name">Sup</div> `; }}
HTML
<whats-up css=" .name{ color: red; } "></whats-up>
长处:款式能够随便批改
毛病:代码不够优雅
五、自定义组件外部定义批改款式函数
示例代码
JS
class Whatsup extends HTMLElement { // ... // 外围代码 reStyle(els, styles) { const elements = Array.isArray(els) ? els : [els]; elements.forEach((element) => Object.assign(element.style, styles)); }}
HTML
<whats-up></whats-up><script> const myEle = document.querySelector('whats-up') const title = myEle.shadowRoot.querySelector('.title'); myEle.reStyle(title, { color: 'red', width: '200px', })</script>
六、通过 slot 内部设置款式
示例代码
JS
class WhatsUp extends HTMLElement { constructor() { super(); const shadowRoot = this.attachShadow({ mode: 'open' }); shadowRoot.innerHTML = ` <div> <slot name="header"></slot> </div> `; }}customElements.define('whats-up', WhatsUp);
HTML
<style> .header{ color: red; }</style><whats-up> <div slot="header" class="header"> what's up </div></whats-up>
七、fetch获取
示例代码
class WhatsUp extends HTMLElement { constructor() { super(); const shadowRoot = this.attachShadow({ mode: 'open' }); // 获取款式 fetch('./index.css').then(res => res.text()).then(data => { let node = document.createElement('style'); node.innerHTML = data; this.shadowRoot.appendChild(node); }); // ... }}customElements.define('whats-up', WhatsUp);
长处:长处是兼容性不错,反对Shadow DOM的元素均反对此语法;以及性能还OK
毛病:不优雅
八、CSS module import
此办法应用浏览器原生的import语法,然而import的是CSS文件而不是JS文件。
也就是把CSS文件间接作为模块引入。
示例代码
import styles from "index.css";class WhatsUp extends HTMLElement { constructor() { // ... // 外围代码 shadow.adoptedStyleSheets = [styles]; }}
长处:长处是应用方便快捷且是官网举荐办法,或者是import CSS模块就是为了这个场景才反对的;以及性能OK,import自身就是异步过程。
毛病:兼容性不佳,狠狠戳这里caniuse。
总结
各种办法实用场景各不相同,小心食用。