第三方 Web 组件(测试版)

注意

此功能是一项测试版服务。客户可自行决定是否试用此类测试版服务。对测试版服务的任何使用均受协议和条款中提供的适用测试版服务条款的约束。

在 LWC 中使用第三方 Web 组件可以节省在 LWC 中重新创建相同组件的时间。要使用第三方 Web 组件,请先启用 Lightning Web Security。Lightning Locker 不支持使用自定义元素,自定义元素是第三方 Web 组件的关键构建块。

在 LWC(测试版)中使用第三方 Web 组件

注意

此功能是一项测试版服务。客户可自行决定是否试用此类测试版服务。对测试版服务的任何使用均受协议和条款中提供的适用测试版服务条款的约束。

在 LWC 应用程序中使用第三方 Web 组件。第三方 Web 组件在 LWC 模板中呈现为本机 Web 组件。尽管您可以使用 iframe 或 在 LWC 模板文件中使用第三方 Web 组件,但我们建议使用 将第三方 Web 组件呈现为 LWC 模板中的本机 Web 组件。lwc:dom="manual"lwc:external

注意

Salesforce 不提供对第三方 Web 组件的支持。演示使用第三方 Web 组件的文档和示例不构成对第三方 Web 组件的认可。我们建议您查看第三方 Web 组件文档,了解使用情况信息。

第三方 Web 组件可以是各种 JavaScript 框架,也可以是用纯 vanilla JS 编写的框架。MDN Web 组件是可与 LWC 框架一起使用的第三方 Web 组件的示例。同样,webcomponents.org 提供了基于自定义元素和影子 DOM 标准的 Web 组件的集合。

如果您使用的是第三方 JavaScript 库,请参阅改用第三方 JavaScript 库。

实现第三方 Web 组件

在使用第三方 Web 组件之前,我们建议您检查 AppExchange 中是否有第三方 LWC 应用程序或组件,并安装具有所需功能的托管软件包。或者,检查基本组件是否适合您的要求。

若要使用非 LWC 第三方 Web 组件,请遵循以下解决方案之一。

  • 将文件作为静态资源上传,并使用模块中的方法加载组件。每个静态资源最多可以上传 5 MB。一个组织最多可以有 250 MB 的静态资源。loadScriptlightning/platformResourceLoader
  • 使用配置文件将第三方 Web 组件添加为 LWC 模块。组件的 JavaScript 文件的最大文件大小为 128 KB。.js-meta.xml

已知问题

此测试版存在几个已知问题。

  • 使用影子 DOM 的第三方 Web 组件仅支持封闭的影子根目录。如果第三方 Web 组件使用模式,请更新源以使组件符合 LWS。或者,使用不使用影子 DOM 的第三方 Web 组件。请参见 Light DOM。attachShadow({ mode: "closed" });open
  • loadScript目前不支持 ECMAScript 模块 (ESM)。例如,不支持。使用预捆绑的 JavaScript 文件和传统格式(如 IIFE(立即调用的函数表达式)或 UMD(通用模块定义))等自定义元素导入第三方 Web 组件。<script type="module">
  • 不支持具有 npm 和其他依赖项的第三方 Web 组件,或者需要编译和捆绑的组件。LWC 目前不支持从 npm 导入。
  • 影子 DOM 不支持按 ID 引用元素的第三方 Web 组件。例如,如果组件使用 ,LWC 无法访问全局 HTML 文档。尽可能使用模板引用。document.getElementById('some-id')
  • 启用 LWS 后,Experience Builder 站点当前不支持第三方 Web 组件。
  • Lightning Web Security 目前不支持使用该选项自定义内置元素。自定义的内置元素在 Safari 等 WebKit 浏览器中也不受支持。若要详细了解在扩展类中可以执行的操作,请参阅 HTML 规范:自定义元素。extendsHTMLElement

使用指南

使用第三方 Web 组件时,请遵循以下准则。

  • 使用特性、属性或指令将数据传递到第三方 Web 组件。将数据传递给 Web 组件时,LWC 默认将数据设置为属性,并且仅当属性存在时才设置属性。lwc:spread
  • 将标记传递到第三方 Web 组件中的插槽,类似于将标记传递到 Lightning Web 组件中的插槽。第三方 Web 组件不支持合成阴影的槽位。
  • LWC 模板仅支持根标记。如果第三方组件需要嵌套标记,请改用 JavaScript 文件。<template><template>document.createElement('template')
  • LWC 模板中的声明性事件绑定只能使用小写事件名称。如果第三方 Web 组件在事件名称中使用非小写字符或连字符,请使用 以编程方式添加事件侦听器。addEventListener()
  • 使用 和 呈现第三方 Web 组件后观察属性更改。observedAttributes()attributeChangedCallback()
  • lwc:external不支持动态组件创建。自定义元素的呈现方式类似于 Lightning Web 组件和原生 HTML 元素。

有关详细信息,请参阅将数据传递到自定义元素 (Beta)。

示例:将 Web 组件作为静态资源上载

此示例中的第三方 Web 组件类似于 lightning-relative-date-time 基本组件。在使用第三方 Web 组件之前,请检查基本组件是否满足您的要求。

此示例使用 time-elements JavaScript 文件,该文件可用作 IIFE。

time-elements提供了多个 Web 组件 – 、 、 和 。local-timerelative-timetime-agotime-until

在使用这些 Web 组件之前,请将 JavaScript 文件作为静态资源上传到组织中。在此示例中,静态资源的名称为 。timeElements

<!--externalExample.html-->
<template>
  <p>
    Relative time (auto-updated every minute):
    <relative-time datetime={date} lwc:external></relative-time>
  </p>
</template>

使用 中的函数导入静态资源。loadScriptlightning/platformResourceLoader

//externalExample.js
import { LightningElement } from "lwc";
import { loadScript } from "lightning/platformResourceLoader";
import timeElements from "@salesforce/resourceUrl/timeElements";

export default class extends LightningElement {
  isCmpInitialized = false;
  error;
  date;

  renderedCallback() {
    if (this.isCmpInitialized) {
      return;
    }
    this.isCmpInitialized = true;

    loadScript(this, timeElements)
      .then(() => {
        this.initializeComponent();
      })
      .catch((error) => {
        this.error = error;
      });
  }
  initializeComponent() {
    this.date = new Date();
  }
}

示例:将 Web 组件添加为 LWC 模块

提示

此示例中的第三方 Web 组件类似于 lightning-helptext 基本组件。在使用第三方 Web 组件之前,请检查基本组件是否满足您的要求。

此示例使用 MDN 中的 popup-info 组件。要将组件添加为 LWC 模块,请在文件夹中创建一个 Lightning Web 组件。让我们命名它。force-app/main/default/lwcpopupInfo

在模板中,在元素上包含指令。lwc:externalpopup-info

<!-- popupInfo.html -->
<template>
  <popup-info
    lwc:external
    img={logo}
    data-text="Here's some popup text for your logo'"
  ></popup-info>
</template>

在 JavaScript 文件中,请确保在模式下创建影子根。此示例使用 附加的静态资源。它还将图像路径替换为 ,该路径引用作为静态资源上传的徽标。closedtrailheadLogopopup-info"img/default.png"{$logo}

//popupInfo.js
import { LightningElement } from "lwc";
import trailheadLogo from "@salesforce/resourceUrl/trailhead_logo";

// Create a class for the element
class PopUpInfo extends HTMLElement {
  constructor() {
    // Always call super first in constructor
    super();

    // Create a shadow root
    this.shadow = this.attachShadow({ mode: "closed" });
  }

  connectedCallback() {
    // Create spans
    const wrapper = document.createElement("span");
    wrapper.setAttribute("class", "wrapper");

    const icon = document.createElement("span");
    icon.setAttribute("id", "test");
    icon.setAttribute("class", "icon");
    icon.setAttribute("tabindex", 0);

    const info = document.createElement("span");
    info.setAttribute("class", "info");

    // Take attribute content and put it inside the info span
    const text = this.getAttribute("data-text");
    info.textContent = text;

    // Insert icon
    const img = document.createElement("img");
    img.src = this.hasAttribute("img") ? this.getAttribute("img") : `{$logo}`;
    icon.appendChild(img);

    // Create some CSS to apply to the shadow dom
    const style = document.createElement("style");

    style.textContent = `
      .wrapper {
        position: relative;
      }
      .info {
        font-size: 0.8rem;
        width: 200px;
        display: inline-block;
        border: 1px solid black;
        padding: 10px;
        background: white;
        border-radius: 10px;
        opacity: 0;
        transition: 0.6s all;
        position: absolute;
        bottom: 20px;
        left: 10px;
        z-index: 3;
      }
      img {
        width: 1.2rem;
      }
      .icon:hover + .info, .icon:focus + .info {
        opacity: 1;
      }
    `;

    // Attach the created elements to the shadow dom
    this.shadow.appendChild(style);
    this.shadow.appendChild(wrapper);
    wrapper.appendChild(icon);
    wrapper.appendChild(info);
  }
}

// Define the new element
customElements.define("popup-info", PopUpInfo);

export default class PopupInfo extends LightningElement {
  logo = trailheadLogo;
}

使用自定义元素(测试版)

注意

此功能是一项测试版服务。客户可自行决定是否试用此类测试版服务。对测试版服务的任何使用均受协议和条款中提供的适用测试版服务条款的约束。

第三方 Web 组件是您可以使用 创建的 Web 组件,从而生成可在 LWC 应用程序中重用的自定义元素。除非使用第三方 Web 组件,否则无需将自定义元素与 LWC 一起使用。就本文而言,自定义元素和第三方 Web 组件是可互换的。customElements.define()

注意

必须在 Salesforce 组织中启用 Lightning Web Security (LWS),因为 Lightning Locker 不支持第三方 Web 组件。

自定义元素必须遵循这些特征。

  • 使用 via 初始化自定义元素。constructor()class
  • 使用阴影 DOM 或浅色 DOM。对于影子 DOM,LWS 仅支持关闭模式。
  • 使用 customElements.define(name, constructor) 在其中注册自定义元素。必须包含连字符,并且在页面上是唯一的。CustomElementRegistryname

在自定义元素中使用标记是可选的。您可以使用 创建标签。您不能在 LWC HTML 模板中使用嵌套标记。<template><template>document.createElement("template");<template>

定义自定义元素

在 LWC 中,只有在使用第三方 Web 组件时才需要自定义元素。在 LWC 中实现第三方 Web 组件时,我们建议您参考该组件的文档以获取使用信息。

第三方 Web 组件包含自定义元素定义,该定义扩展了 HTMLElement 类。自定义元素定义描述如何显示元素以及添加或删除元素时要执行的操作。

class MyCustomElement extends HTMLElement {
  constructor() {
    super();
    /* custom element created */
  }
  connectedCallback() {
    /* element is added to document */
  }
  disconnectedCallback() {
    /* element is removed from the document */
  }
  static get observedAttributes() {
    return [
      /* array of attribute names to monitor for changes */
    ];
  }
  attributeChangedCallback(name, oldValue, newValue) {
    /* one of attributes listed above is modified */
  }
  adoptedCallback() {
    /* element is moved to a new document */
  }
}
/* register the element */
customElements.define("my-custom-element", MyCustomElement);

第三方 Web 组件行为在生命周期回调中描述,例如 in 或 。connectedCallback()disconnectedCallback()

  • constructor()-在初始化自定义元素时调用。它必须调用并可以指定任何预渲染过程,例如设置阴影的内容。super()
  • connectedCallback()-在自定义元素连接到 DOM 时调用。
  • disconnectedCallback()-在自定义元素与 DOM 断开连接时调用。
  • observedAttributes()-返回要观察的属性数组。
  • attributeChangedCallback()-在添加、删除或更改属性时调用。指定要在 中观察的属性。observeAttributes()
  • adoptedCallback()-在将自定义元素移动到新文档时调用。

创建自定义元素构造函数

在 LWC 中,只有在使用第三方 Web 组件时才需要自定义元素。在 LWC 中实现第三方 Web 组件时,我们建议您参考该组件的文档以获取使用信息。

第三方 Web 组件包含一个构造函数,用于设置初始状态和默认值、设置事件侦听器以及创建影子根。

若要建立原型链,请调用构造函数。使用 将影子根附加到自定义元素。LWS 要求将模式设置为 。了解 Lightning Web Security 与 Lightning Locker 的比较结果。super()this.attachShadow()closed

注意

在关闭模式下,该属性返回 null,因此不能使用 来访问和操作元素的影子根。在闭合模式下创建自定义元素时,请使用其他变量(如 或 )保存对影子根的引用。shadowRootshadowRootshadow__shadowRoot

要创建元素的内部影子 DOM 结构,请使用 追加内容。此示例定义 LWC 组件生命周期之外的自定义元素。.innerHTML

//myComponent.js
import { LightningElement } from "lwc";

customElements.define(
  "my-custom-element",
  class extends HTMLElement {
    constructor() {
      super();
      this.attachShadow({ mode: "closed" }).innerHTML = "<div>Custom Element Constructor</div>";
    }
  },
);

export default class MyComponent extends LightningElement {
  greeting = "World";
}

若要使用自定义元素的属性和子元素,请改用 or。例如,如果要创建元素并在其上设置属性,请将它们推迟到生命周期回调之一,并在属性更改时用于定义回调。有关详细信息,请参阅自定义元素规范。connectedCallback()renderedCallback()attributeChangedCallback()

在 LWC 中使用自定义元素

将 LWC 模板中的自定义元素与指令一起使用。lwc:external

<!-- myComponent.html -->
<template>
  <div class="slds-var-m-around_medium">Hello, {greeting}!</div>
  <my-custom-element lwc:external></my-custom-element>
</template>

示例:创建递增按钮标签的自定义元素

以下示例演示了自定义元素的结构。该示例创建一个按钮,按下该按钮时,该按钮的标签上的计数器会递增。

//myCounterButton.js
import { LightningElement } from "lwc";

customElements.define(
  "my-counter",
  class extends HTMLElement {
    count = 0;
    handler = null;
    shadow = null;
    constructor() {
      super();
      this.shadow = this.attachShadow({ mode: "closed" });
      this.shadow.innerHTML = `Button:<button>${this.count}</button>`;
    }
    connectedCallback() {
      this.handler = () => {
        this.count++;
        this.shadow.firstElementChild.innerHTML = this.count;
      };
      this.shadow.firstElementChild.addEventListener("click", this.handler);
    }
    disconnectedCallback() {
      this.shadow.firstElementChild.removeEventListener("click", this.handler);
    }
  },
);

export default class MyCounterButton extends LightningElement {
  // your LWC component definition here
}

若要在 LWC 中使用自定义元素,请使用指令将其添加到模板中。lwc:external

<!-- myCounterButton.html -->
<template>
  <my-counter lwc:external></my-counter>
</template>

该组件在 DOM 中呈现如下。每次单击按钮标签时,按钮标签都会递增。${this.count}

<my-counter-button>
    <my-counter>
      #shadow-root (closed)
      |  "Button:"
      |  <button>0</button>
    </my-counter>
</my-counter-button>

示例:使用属性更改回调递增按钮

此示例与上一个示例类似,但它监视自定义元素的属性,用于在属性更改时定义回调。countattributeChangedCallback()

//myCounterWithCallback.js
import { LightningElement } from "lwc";

customElements.define(
  "my-counter",
  class MyCounter extends HTMLElement {
    constructor() {
      super();
      this.shadow = this.attachShadow({ mode: "closed" });
    }

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

    set count(val) {
      this.setAttribute("count", val);
    }

    connectedCallback() {
      this.renderButton();
      let btn = this.shadow.querySelector("#btn");
      btn.addEventListener("click", this.increment.bind(this));
    }

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

    attributeChangedCallback(prop, oldVal, newValue) {
      if (prop === "count") {
        this.renderButton();
        let btn = this.shadow.querySelector("#btn");
        btn.addEventListener("click", this.increment.bind(this));
        // do something else
      }
    }

    increment() {
      this.count++;
    }

    renderButton() {
      this.shadow.innerHTML = `
        <button id="btn">${this.count}</button>
      `;
    }
  },
);

export default class extends LightningElement {}

将自定义元素标签添加到 LWC 模板。

<!-- myCounterWithCallback.html -->
<template>
  <my-counter count="0" lwc:external></my-counter>
</template>

将数据传递到自定义元素(测试版)

自定义元素是第三方 Web 组件的构建基块。使用特性、属性或 lwc:spread 指令将数据传递到自定义元素。传递数据时,LWC 默认将数据设置为属性,并且仅当属性存在时才设置属性。

初始化影子内容的构造函数仅调用一次。在使用特性或属性时,请考虑这些准则。this.attachShadow({ mode: 'closed' })

使用属性传递数据

呈现第三方 Web 组件后,将忽略属性更改。要观察属性并确保第三方 Web 组件呈现您的更改,请使用静态 getter 和方法。当观察到的属性发生更改时,回调将运行。若要处理属性数据的序列化和反序列化,请使用 getter 和 setter,如本示例所示。observedAttributes()attributeChangedCallback()attributeChangedCallback()

class extends HTMLElement {
    static observedAttributes = ["myAttr"];
    attributeChangedCallback(attr, oldVal, newVal) {
      if (attrName === "myAttr") {
        this.shadow.getElementById("myElement").myAttr = newVal === "true";
      }
    }
    set myAttr(bool) {
      this.setAttribute("myAttr", bool.toString());
    }
    get myAttr() {
      return this.getAttribute("myAttr") === "true";
    }
}

请参阅使用属性更改递增按钮的示例。

使用属性传递数据

要使用属性,请使用 getter 和 setter。

class extends HTMLElement {
  _message = 'Hello';
  set message(value) {
    this._message = value;
  }
  get message() {
    return this._message;
  }
}

例如,您有一个自定义元素,该元素具有使用 lwc:spread 指令传递给自定义元素的属性。

<!-- myMessage.html -->
<template>
  <c-message lwc:external lwc:spread={props}></c-message>
</template>

自定义元素显示一个按钮。要向按钮添加事件侦听器,请使用 。addEventListener()

// myMessage.js
import { LightningElement } from "lwc";

customElements.define(
  "c-message",
  class extends HTMLElement {
    constructor() {
      super();
      this.shadow = this.attachShadow({ mode: "closed" });
      this.shadow.innerHTML = `<button>click</button>`;
      this.shadow.querySelector("button").addEventListener("click", (event) => {
        console.log(`message: ${this.message}`);
      });
    }

    set message(value) {
      this._message = value;
    }
    get message() {
      return this._message;
    }
  },
);

export default class MyMessage extends LightningElement {
  props = {
    message: "Hello custom element",
  };
}

将数据传递到子组件

考虑一个父组件,该组件包含定义自定义元素的子组件。使用 lwc:spread 指令将属性传递给子组件。

<!-- myApp.html -->
<template>
  <c-cmp lwc:spread={myProps}></c-cmp>
</template>

使用具有键值对的对象。

// myApp.js
import { LightningElement } from "lwc";

export default class MyApp extends LightningElement {
  myProps = {
    name: "Guest",
    greeting: "Hello",
  };
}

在子组件中,创建自定义元素的实例。

<!-- myCmp.html -->
<template>
  <c-custom-el lwc:external> {greeting}, {name} </c-custom-el>
</template>

在 JavaScript 中调用 并将属性公开给父组件。constructor()

// myCmp.js
import { LightningElement, api } from "lwc";

customElements.define(
  "c-custom-el",
  class extends HTMLElement {
    constructor() {
      super();
      this.attachShadow({ mode: "closed" }).innerHTML = "<slot></slot>";
    }
  },
);
export default class MyCmp extends LightningElement {
  @api name;
  @api greeting;
}

自定义元素的呈现方式如下。

<my-app>
  #shadow-root (open)
  |  <my-cmp> 
  |    #shadow-root (open) 
  |    |  <c-custom-el>
  |    |    #shadow-root (closed)
  |    |    | Hello, Guest
  |    |  </c-custom-el>
  |  </my-cmp>
</my-app>

将标记传递到自定义元素中的槽

将标记传递到第三方 Web 组件中的槽的行为类似于 LWC 组件中的槽。

注意

第三方 Web 组件不支持合成阴影的开槽实现。

考虑使用带有一些标记的第三方 Web 组件。

customElements.define(
  "c-custom-slot",
  class extends HTMLElement {
    constructor() {
      super();
      this.attachShadow({ mode: "closed" }).innerHTML = `
    <h1>My title</h1>
    <div>
        <p>Some content here</p>
    </div>
    <slot></slot>
    `;
    }
  },
);

以下槽位内容将显示在元素中。<slot>

<template>
  <c-custom-slot lwc:external>
    <div class="slotted">slot content</div>
  </c-custom-slot>
</template>

该组件在 DOM 中呈现如下。

<c-custom-slot>
  #shadow-root (closed)
  |  <h1>My title</h1>
  |  <div><p>Some content here</p></div>
  |  <slot>
  |    <div class="slotted">slot content</div>
  |  </slot>
</c-custom-slot>

同样,您可以使用这样的命名槽。

// mySlot.js
import { LightningElement, api } from "lwc";

customElements.define(
  "c-slotting",
  class extends HTMLElement {
    constructor() {
      super();
      this.shadow = this.attachShadow({ mode: "closed" });
      this.shadow.innerHTML = `<slot name="myslot"></slot>`;
    }
  },
);
export default class MySlot extends LightningElement {}

在标记中包含命名槽。

<!-- mySlot.html -->
<c-slotting lwc:external>
  <p>slotted incorrectly</p>
  <p slot="myslot">slotted correctly</p>
</c-slotting>

该组件在 DOM 中呈现如下。

<my-slot>
  #shadow-root (open)
  |  <c-slotting>
  |    #shadow-root (closed)
  |    |  <p>slotted incorrectly</p>
  |    |  <p slot="myslot">slotted correctly</p>
  |  </c-slotting>
</my-slot>

在本机影子组件中,插槽内容保留在顶级元素中。CustomElementConstructor

例如,文件中的此顶级元素包括插槽内容。<slot>index.html

<c-custom-slot>
  <div class="slotted">Pre-existing slot content</div>
</c-custom-slot>

该组件在 DOM 中呈现如下。它保留了原始的插槽内容。

<c-custom-slot>
  #shadow-root (closed)
  |  <slot>
  |    <div class="slotted">Pre-existing slot content</div>
  |  </slot>
</c-custom-slot>

使用第三方 Web 组件中的事件

第三方 Web 组件中的事件与 LWC 中的事件类似。事件绑定仅支持小写事件。要使用具有非小写名称的事件,请使用 addEventListener() API 添加事件侦听器。

在 中添加事件侦听器。constructor()

customElements.define(
  "c-element-with-events",
  class extends HTMLElement {
    constructor() {
      super();
      this.attachShadow({ mode: "closed" });
      this.shadow.innerHTML = `CLICK ME!`;
      this.addEventListener("click", this.handleClick);
    }
    handleClick() {
      this.dispatchEvent(new CustomEvent("lowercaseevent"));
      this.dispatchEvent(new CustomEvent("camelEvent"));
    }
  },
);

第三方 Web 组件注意事项

未注册的自定义元素呈现为本机接口的实例,该实例在不添加任何属性或方法的情况下进行扩展。然后,浏览器将外部组件视为本机组件,与 a 或 .HTMLUnknownElementHTMLElementspandiv

对于已注册的组件,引擎会呈现关联的第三方 Web 组件,并将升级推迟到浏览器。

有关更多信息,请参见 HTML 规范:在创建元素后升级元素。

此外,请考虑第三方 Web 组件上的这些升级行为。

  • 如果未升级第三方 Web 组件,LWC 会在挂载和更新时设置其属性。
  • 如果存在延迟升级,则设置属性而不是属性。
  • 升级后,如果属性存在,则设置该属性而不是该属性。

将样式追加到自定义元素(测试版)

第三方 Web 组件可以包含在影子 DOM 或轻量级 DOM 中创建的自定义元素。对于影子 DOM,开放模式比封闭模式更广泛地使用。要了解您正在使用的第三方 Web 组件是否正在使用特定的影子模式,请参阅 Web 组件文档。或者,查看 Web 组件源并查找方法。使用轻量级 DOM 的 Web 组件不使用该方法。attachShadow({mode: 'closed|open'})attachShadow()

确定第三方 Web 组件的 DOM 模型后,可以决定如何设置自定义元素及其内部结构的样式。

在 Shadow DOM 中实现自定义元素样式

使用影子 DOM,自定义元素无法从其容器组件继承样式。同样,在自定义元素中定义的样式也不会渗出。在关闭模式下,您无法将样式附加到自定义元素的影子 DOM。例如,返回 null。this.refs.myEl.shadowRoot

许多 Web 组件作者通过将标记附加到影子根来实现自定义元素的样式。查看 Web 组件源并查找与这些行类似的行。这些样式的范围限定在影子根内。<style>

const style = document.createElement("style");
style.textContent = `.someSelector { color: red }`;
this.shadow.appendChild(style);

若要在闭合模式下追加样式,可以使用 CSS 变量(自定义属性)、类或阴影部分。除了第三方 Web 组件上的影子根样式实现之外,我们不建议使用 JavaScript 来定义 CSS 样式。

Web 组件作者允许您覆盖影子根中的样式(如果它们包含这样的 CSS 自定义属性)。

提示

查看第三方 Web 组件源代码或文档,了解可用于设置组件中自定义元素样式的可用 CSS 自定义属性和阴影部件。

style.textContent = `.someSelector { color: var(--my-title-color, 	#AA4A44)}`;

由于 CSS 自定义属性会渗入影子 DOM,因此您可以覆盖主机组件中的样式。

假设第三方 Web 组件提供了带有 CSS 自定义属性的边框样式。在主机组件中,使用具有您自己的值的 CSS 定制属性。border: var(--my-border, 1px solid black);--my-border

/* popupInfo.css */
:host {
  --my-border: 1px solid green;
}

如果要设置第三方自定义元素的 host 元素的样式,请对文件中的自定义元素使用选择器,例如 ..cssc-custom-el { background-color: red; }

<!--styleExample.html -->
<template>
  <c-custom-el lwc:external></c-custom-el>
</template>

选择器将红色背景应用于自定义元素的内容。c-custom-el

/* styleExample.css */
c-custom-el {
  background-color: red;
}

自定义元素的呈现方式如下。

<c-style-example>
  #shadow-root (open)
  |  <c-custom-el>
  |    #shadow-root (closed)
  |    |  <slot>your text here</slot>
  |   </c-custom-el>
</c-style-example>

在 Light DOM 中实现自定义元素样式

与影子 DOM 不同,轻量级 DOM 支持从根文档设置样式以定位 DOM 节点并设置其样式。因此,容器组件上的样式级联到嵌套的自定义元素的轻量级 DOM 中。在轻量级 DOM 中呈现的自定义元素上的样式也会应用于其容器组件,直到遇到阴影边界。

如果第三方 Web 组件使用轻量级 DOM,则可以使用文件中的类来设置自定义元素内部的样式。要在自定义元素中限定样式范围,请使用组件包中的文件包含样式。.css.scoped.css

<!--styleExample.html-->
<template>
  <custom-element class="highlight" lwc:external></custom-element>
</template>

在 css 文件中,提供自定义样式。

.highlight {
  color: red;
}