中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

常州做網(wǎng)站麥策電商戶外廣告

常州做網(wǎng)站麥策電商,戶外廣告,seo網(wǎng)站點(diǎn)擊量排名優(yōu)化,wordpress素材模板[React]利用Webcomponent封裝React組件 為什么這么做 我個人認(rèn)為,最重要的點(diǎn)是可以很方便地跨框架掛載和卸載wc元素(至少我在項目里是這么玩的),此外,基于wc的css沙箱以及它的shadowRoot機(jī)制,可以提供一套…

[React]利用Webcomponent封裝React組件

為什么這么做

我個人認(rèn)為,最重要的點(diǎn)是可以很方便地跨框架掛載和卸載wc元素(至少我在項目里是這么玩的),此外,基于wc的css沙箱以及它的shadowRoot機(jī)制,可以提供一套隔離機(jī)制,保證每個渲染組件的邊界分明。

利用AI總結(jié)羅列了一下都有啥優(yōu)點(diǎn)…

  1. 封裝性:Web Components提供了一種封裝UI組件的方法,使得組件可以在不同的框架或無框架環(huán)境中重用。
  2. 可重用性:封裝為Web Components的React組件可以在任何支持Web Components的環(huán)境中使用,不限于React應(yīng)用。
  3. 封裝的樣式和行為:Web Components允許你封裝組件的HTML結(jié)構(gòu)、樣式和行為,確保樣式和行為不會泄露到父組件或全局作用域。
  4. 獨(dú)立性:Web Components封裝的組件具有獨(dú)立性,它們擁有自己的DOM樹和作用域,不會影響外部環(huán)境。
  5. 易于集成:Web Components提供了一種標(biāo)準(zhǔn)化的集成方式,可以更容易地將React組件集成到其他Web應(yīng)用中。
  6. 更好的性能:Web Components的自定義元素可以在不影響主線程的情況下進(jìn)行升級和渲染,這有助于提高應(yīng)用性能。
  7. 標(biāo)準(zhǔn)化:Web Components基于W3C標(biāo)準(zhǔn),這意味著它們在不同的瀏覽器和環(huán)境中具有更好的一致性和兼容性。
  8. 易于維護(hù):由于Web Components封裝的組件具有清晰的接口和封裝性,維護(hù)和更新組件變得更加容易。
  9. 樣式隔離:Web Components的Shadow DOM技術(shù)可以確保組件的樣式不會受到外部樣式的影響,同時也防止組件內(nèi)部樣式泄露到外部。
  10. 生命周期管理:Web Components允許你定義組件的生命周期鉤子,如connectedCallbackdisconnectedCallback等,這與React組件的生命周期方法類似。
  11. 跨框架使用:封裝為Web Components的React組件可以被其他前端框架或庫使用,例如Vue、Angular或原生JavaScript。
  12. 自定義元素:Web Components允許開發(fā)者定義自定義HTML元素,這些元素可以像標(biāo)準(zhǔn)HTML元素一樣使用。
  13. 易于測試:Web Components的封裝性使得測試組件變得更加簡單,因為你可以獨(dú)立于其他組件來測試它們。
  14. 更好的封裝和抽象:Web Components提供了一種封裝和抽象UI組件的方式,使得組件的實現(xiàn)細(xì)節(jié)對使用者是透明的。

Webcomponent入門

先來簡單地過一下webcomponent的基礎(chǔ)

官方文檔:https://developer.mozilla.org/zh-CN/docs/Web/API/Web_components

示例

下面是一個最簡單的示例,自定義了一種名為”simple-component“的元素,并且它沒有shadowRoot(意味著它并沒有與外界隔離樣式)。

class SimpleComponent extends HTMLElement {constructor() {super();this.innerHTML = `<p>Hello, World!</p>`;}
}customElements.define('simple-component', SimpleComponent);

下面是一個內(nèi)容更豐富一些的示例,有基礎(chǔ)的大概過一眼也知道大概了。

//  1.自定義標(biāo)簽都是用class 的形式去繼承
class myDiv extends HTMLElement {// 監(jiān)聽static get observedAttributes() {return ['option']}constructor() {super()// 這樣我們才能夠去追加元素this.attachShadow({ mode: 'open' })}// 重要:生命周期方法 開始connectedCallback() {console.log('connectedCallback生命周期')this.render({option: this.getAttribute('option'),})// 獲取元素console.log(this.shadowRoot.querySelector('.content'))console.log('this.shadowRoot: ', this.shadowRoot)document.addEventListener('click', e => {// 重要:冒泡的順序,通過這個可以判斷有沒有在鼠標(biāo)內(nèi)部進(jìn)行點(diǎn)擊if (e.composedPath().includes(this)) {console.log('點(diǎn)擊了里面')}})this.shadowRoot.querySelector('.content').addEventListener('click', e => {console.log('e: ', e)// window.dispatchEvent})}// 重要:生命周期方法 重新渲染 .甚至還是第一次進(jìn)行渲染,比connect還快// 會重新渲染 connectCallbackattributeChangedCallback(attr, oldValue, newValue) {if (oldValue) {switch (attr) {case 'option':this.shadowRoot.querySelector('.title').textContent = newValue}}console.log('attributeChangeCallback', attr, oldValue, newValue)}borderAdd() {console.log('borderadd')this.shadowRoot.querySelector('.content').style.border = '3px solid green'}render(data) {let { option } = data// console.log()let nodeTemplate = document.createElement('template')nodeTemplate.innerHTML = `<div class="content" ><div class="title">${option} </div> <slot name="container"></slot></div>`let nodeStyles = document.createElement('style')// shadow dom 的樣式絕對隔離// 重要: :host選擇器可以選中根也就是my-div的樣式。外面的選擇器樣式要高于這個nodeStyles.innerHTML = `:host(.active) .content{margin-top:20px;background:rgba(0,0,0,30%);}:host{display:block}.content{width:100px;height:100px;background:rgba(0,0,0,20%)}::slotted([slot="container"]){display:none}::slotted(.active){display:block}`this.shadowRoot.appendChild(nodeTemplate.content)this.shadowRoot.appendChild(nodeStyles)setTimeout(() => {this.borderAdd()}, 3000)}
}// 名字必須小寫 駝峰必須要轉(zhuǎn)成橫線
customElements.define('my-div', myDiv)

shadowRoot

一個Web組件可以有且僅有一個shadowRoot。shadowRoot是與該組件關(guān)聯(lián)的影子DOM的根節(jié)點(diǎn)。當(dāng)使用attachShadow方法創(chuàng)建影子DOM時,它會返回一個shadowRoot對象,這個對象是唯一的,并且與創(chuàng)建它的元素關(guān)聯(lián)。

例如:

class MyComponent extends HTMLElement {constructor() {super();this.shadow = this.attachShadow({ mode: "open" });this.shadow.innerHTML = `<p>I am in the shadow DOM!</p>`;}
}customElements.define('my-component', MyComponent);

在這個例子中:

  • MyComponent類擴(kuò)展了HTMLElement,定義了一個Web組件。
  • 在構(gòu)造函數(shù)中,通過調(diào)用this.attachShadow({ mode: "open" })創(chuàng)建了一個shadowRoot,并將其存儲在this.shadow變量中。
  • 這個shadowRoot是唯一的,并且與MyComponent實例關(guān)聯(lián)。

關(guān)鍵點(diǎn):

  • 唯一性:每個Web組件實例只能有一個shadowRoot。
  • 關(guān)聯(lián)性shadowRoot與創(chuàng)建它的Web組件實例是緊密關(guān)聯(lián)的,不能被其他組件實例訪問。

因此,盡管可以在shadowRoot內(nèi)創(chuàng)建多個子元素和結(jié)構(gòu),但每個Web組件實例只能有一個shadowRoot。這有助于保持組件的封裝性和獨(dú)立性。

生命周期

  1. connectedCallback
    • 當(dāng)自定義元素被插入到文檔DOM樹中時調(diào)用此方法。這類似于React中的componentDidMount。
  2. disconnectedCallback
    • 當(dāng)自定義元素從DOM樹中移除時調(diào)用此方法。類似于React中的componentWillUnmount。
  3. attributeChangedCallback
    • 當(dāng)自定義元素的屬性被更改時調(diào)用此方法。它接收三個參數(shù):屬性名稱、舊值和新值。這可以用于響應(yīng)屬性的變化,類似于React中的componentDidUpdate,但是它是針對屬性而不是狀態(tài)。
  4. adoptedCallback
    • 當(dāng)自定義元素被移動到新的文檔時調(diào)用此方法。這在Web Components中是特有的,因為自定義元素可以跨文檔使用。

主要屬性

  1. 觀察者模式(Observed attributes)
    • 通過在自定義元素類中定義一個靜態(tài)的observedAttributes屬性數(shù)組,可以指定哪些屬性的更改應(yīng)該觸發(fā)attributeChangedCallback。
  2. connecteddisconnected 屬性
    • 這些屬性可以用于檢查自定義元素是否已經(jīng)連接到文檔的DOM樹中。
  3. shadowRoot 屬性
    • 每個自定義元素都有一個shadowRoot屬性,它是一個Shadow DOM樹的根??梢栽谶@個屬性上使用生命周期回調(diào)來管理Shadow DOM的創(chuàng)建和更新。
  4. constructor
    • 雖然不是Web Components的生命周期回調(diào),但是自定義元素的構(gòu)造函數(shù)是定義元素屬性和方法的地方,并且在元素實例化時調(diào)用。

Lit框架入門

一般知道了上面的基礎(chǔ),就可以寫wc組件了,但實際開發(fā)中,肯定還是需要借助一些已有的開發(fā)框架來輔助開發(fā),而Lit就是目前最成熟且使用量最高的。

原理介紹

Web組件的更新并不是每次都進(jìn)行全量更新。Web組件的更新機(jī)制非常靈活,能夠根據(jù)組件的狀態(tài)和屬性的變化來決定是否需要更新。以下是一些關(guān)鍵點(diǎn):

  1. 屬性變化觸發(fā)更新

    • Web組件的更新通常是由屬性的變化觸發(fā)的。當(dāng)組件的屬性發(fā)生變化時,瀏覽器會調(diào)用attributeChangedCallback方法來處理這些變化。
  2. 狀態(tài)變化觸發(fā)更新

    • 組件的內(nèi)部狀態(tài)變化也可能導(dǎo)致更新。例如,在LitElement中,當(dāng)使用@property裝飾器定義的屬性發(fā)生變化時,會觸發(fā)更新。
  3. 生命周期方法

    • 組件的生命周期方法,如connectedCallback, disconnectedCallback, adoptedCallback, firstUpdated, updated等,都可以在特定時機(jī)觸發(fā)更新。
  4. 選擇性更新

    • 更新機(jī)制可以是選擇性的。例如,在LitElement中,可以通過使用requestUpdate方法來請求更新,而不必每次都進(jìn)行全量更新。
  5. 虛擬DOM

    • 一些Web組件框架(如LitElement)使用虛擬DOM技術(shù)來優(yōu)化更新過程。虛擬DOM可以比較組件的新舊狀態(tài),并只更新那些實際發(fā)生變化的部分。
  6. 優(yōu)化性能

    • 為了避免不必要的全量更新,Web組件通常會使用一些優(yōu)化技術(shù),例如節(jié)流(throttle)和防抖(debounce)來減少更新次數(shù)。
  7. 自定義渲染邏輯

    • 開發(fā)者可以通過自定義渲染邏輯來控制組件的更新過程。例如,可以在render方法中手動決定哪些部分需要重新渲染。
  8. 條件渲染

    • 組件可以通過條件渲染來決定是否需要更新某些部分。例如,只有當(dāng)特定條件滿足時才重新渲染某些元素。

示例

以下是一個使用LitElement的示例,展示了如何控制組件的更新:

import { LitElement, html, css, property } from 'lit';class MyComponent extends LitElement {@property({ type: String })message = '';render() {return html`<div><p>${this.message}</p></div>`;}updated(changedProperties) {super.updated(changedProperties);if (changedProperties.has('message')) {console.log('Message updated:', this.message);}}
}customElements.define('my-component', MyComponent);

在這個示例中:

  • message屬性使用@property裝飾器定義,當(dāng)其值發(fā)生變化時,會觸發(fā)組件的更新。
  • render方法定義了組件的渲染邏輯,只有當(dāng)message屬性發(fā)生變化時,相關(guān)的部分才會重新渲染。
  • updated方法在組件更新后被調(diào)用,可以在這里處理更新后的邏輯。

通過這種方式,Web組件可以有效地控制更新過程,避免不必要的全量更新,從而提高性能。

增加的生命周期和內(nèi)置屬性

Lit 相對于傳統(tǒng) Web 組件規(guī)范增加的一些生命周期鉤子和特性:

  1. render 方法

    • 這是 Lit 的核心特性之一。render 方法是一個返回組件模板的函數(shù),Lit 會根據(jù)這個方法的內(nèi)容來渲染組件的 UI。
  2. update 方法

    • 這個方法在組件的屬性或狀態(tài)發(fā)生變化時被調(diào)用。Lit 會調(diào)用這個方法來決定是否需要重新渲染組件。
  3. shouldUpdate 方法

    • 這個方法允許開發(fā)者自定義更新邏輯,決定是否需要進(jìn)行更新。如果返回 false,則跳過更新。
  4. willUpdate 方法

    • 在組件更新之前被調(diào)用,可以用于執(zhí)行更新前的準(zhǔn)備工作。
  5. updated 方法

    • 在組件更新之后被調(diào)用,可以用于執(zhí)行更新后的邏輯處理。
  6. firstUpdated 方法

    • 在組件首次更新后被調(diào)用。這與 Web 組件的 connectedCallback 有些相似,但專門用于處理首次渲染后的邏輯。
  7. connectedCallback

    • 這是 Web 組件規(guī)范中的方法,Lit 也支持。當(dāng)組件被插入到文檔中時調(diào)用。
  8. disconnectedCallback

    • 這是 Web 組件規(guī)范中的方法,Lit 也支持。當(dāng)組件從文檔中移除時調(diào)用。
  9. attributeChangedCallback

    • 這是 Web 組件規(guī)范中的方法,Lit 也支持。當(dāng)組件的屬性發(fā)生變化時調(diào)用。
  10. adoptedCallback

    • 這是 Web 組件規(guī)范中的方法,Lit 也支持。當(dāng)組件被移動到新文檔時調(diào)用。
  11. requestUpdate 方法

    • 這個方法可以被開發(fā)者調(diào)用,以請求更新組件的屬性。Lit 會安排在下一個微任務(wù)中處理這些更新。
  12. updateComplete Promise

    • 一個 Promise,當(dāng)組件的更新完成后會解析。這可以用于在更新完成后執(zhí)行異步操作。
  13. 樣式管理

    • Lit 提供了 CSSResultunsafeCSS 等 API,用于更安全和方便地管理組件的樣式。
  14. 屬性裝飾器

    • 使用 @property 裝飾器定義的屬性會觸發(fā)更新,并且可以指定屬性的類型和是否同步到 DOM 屬性。
  15. 狀態(tài)管理

    • Lit 通過 state 方法和 reactive 裝飾器,提供了一種聲明式的方式來管理組件的狀態(tài)。

核心:結(jié)合Lit框架實現(xiàn)React組件封裝

那么基于以上,我們可以很容易地就實現(xiàn)利用Lit框架創(chuàng)造出一個webcomponent容器,然后用來包裹React組件。

Base基礎(chǔ)類

import { LitElement, ReactiveElement, adoptStyles, unsafeCSS, PropertyValues } from 'lit'
import { property } from 'lit/decorators.js'type ThrottleFn = (...args: any[]) => void
type DelayFn = (fn: ThrottleFn) => voidconst throttleWith = <T extends ThrottleFn>(fn: T,delayFn: DelayFn,leading = false
): T => {let lastArgs: Parameters<T>, lastThis: unknown, isWaiting = falseconst throttledFn = (...args: Parameters<T>) => {lastArgs = args// eslint-disable-next-linelastThis = thisif (!isWaiting) {if (leading) {fn.apply(lastThis, lastArgs)}isWaiting = truedelayFn(() => {fn.apply(lastThis, lastArgs)isWaiting = false})}}return throttledFn as T
}export default class Base extends LitElement {private _wcStyle?: string@property({ attribute: 'wc-style' })get wcStyle() {return this._wcStyle}set wcStyle(val: string | undefined) {this._wcStyle = valthis.adoptStyles()}/*** 使事件不能跨越ShadowDOM邊界傳播*/@property({ type: Boolean, attribute: 'prevent-compose' })protected preventCompose = false/*** 使事件不冒泡*/@property({ type: Boolean, attribute: 'prevent-bubbles' })protected preventBubbles = false// 應(yīng)用樣式protected adoptStyles = throttleWith(() => {const apply = () => {if (this.renderRoot instanceof ShadowRoot) {const styles = (this.constructor as typeof ReactiveElement).elementStyles.slice() // 獲取原有樣式this.wcStyle && styles.push(unsafeCSS(this.wcStyle))adoptStyles(this.renderRoot, styles) // 重新應(yīng)用樣式}}this.renderRoot ? apply() : this.updateComplete.then(apply)},(fn: any) => Promise.resolve().then(fn))// 派發(fā)事件emit(eventName: string, detail?: any, options?: CustomEventInit) {let event = new CustomEvent(eventName, {detail,composed: !this.preventCompose,bubbles: !this.preventBubbles,cancelable: false,...options,})this.dispatchEvent(event)return event}// 判斷 slot 是否傳入內(nèi)容hasSlot(name?: string) {if (name && name !== 'default') {return !![...this.childNodes].find(node => node.nodeType === node.ELEMENT_NODE && (node as Element).getAttribute('slot') === name)}return [...this.childNodes].some(node => {if (node.nodeType === node.TEXT_NODE && !!node.textContent?.trim()) {return true}if (node.nodeType === node.ELEMENT_NODE) {const el = node as HTMLElementif (!el.hasAttribute('slot')) {return true}}return false})}// 各個生命周期// 掛載時connectedCallback() {super.connectedCallback()console.log('Custom element added to page.')// 第一次被插入文檔時執(zhí)行,跳過節(jié)點(diǎn)刪除后又重新插入的情形if (!this.hasUpdated) {this.setAttribute('wc-component', '')this.setAttribute('wc-pending', '')}}// 卸載時disconnectedCallback() {super.disconnectedCallback()console.log('Custom element removed from page.')}// 移動到另一個文檔的時候adoptedCallback() {console.log('Custom element moved.')}// 元素的屬性被添加、刪除或修改時調(diào)用attributeChangedCallback(name: string, oldValue: any, newValue: any) {super.attributeChangedCallback(name, oldValue, newValue)console.log(`Attribute ${name} has changed.`)}// 或使用靜態(tài)屬性代替get方法static get observedAttributes() {// 指定要監(jiān)聽的元素的屬性數(shù)組// 對應(yīng)的attr改變后,會觸發(fā)attributeChangedCallback// return ['name', 'date']return []}// 是否應(yīng)該更新protected shouldUpdate(_changedProperties: PropertyValues): boolean {return true}// 即將更新protected willUpdate(_changedProperties: PropertyValues): void {super.willUpdate(_changedProperties)console.log('willUpdate')}// 首次更新元素時調(diào)用。實現(xiàn)在更新后對元素執(zhí)行一次性工作protected firstUpdated(changedProperties: PropertyValues) {super.firstUpdated(changedProperties)console.log('this.hasUpdated: ', this.hasUpdated)// this.requestUpdate()// 兩幀數(shù)后執(zhí)行requestAnimationFrame(() => {requestAnimationFrame(() => {this.removeAttribute('wc-pending')})})}protected updated(_changedProperties: PropertyValues): void {super.updated(_changedProperties)this.updateComplete.then((res) => {console.log('updateComplete', res)})}
}

withProperties封裝

import type { LitElement, PropertyValues } from 'lit'type Constructor<T> = new (...args: any[]) => Texport default <T extends Constructor<LitElement>>(superClass: T) => {class WithPropertiesElement extends superClass {props: Record<string, any> = {}willUpdate(changedProperties: PropertyValues) {const obj = [...changedProperties.entries()].reduce<any>((obj, [key]) => ((obj[key] = (this as any)[key]), obj),{})this.props = { ...this.props, ...obj }super.willUpdate(changedProperties)}}return WithPropertiesElement as Constructor<{props: Record<string, any>}> & T
}

這段代碼定義了一個高階組件(Higher-Order Component,HOC),用于增強(qiáng) LitElement 組件的功能。具體來說,它的作用是:

  1. 創(chuàng)建一個帶有額外屬性管理功能的組件類

    • 通過擴(kuò)展傳入的基類(比如 LitElement 或其子類),添加一個 props 屬性來存儲組件的屬性值。
  2. 在組件更新前處理屬性變化

    • 重寫 willUpdate 生命周期方法,這個方法在組件的屬性發(fā)生變化并且組件即將更新之前被調(diào)用。
  3. 收集并存儲屬性變化

    • 使用 changedProperties 對象(一個 Map 類型的對象,包含屬性名和屬性變化的信息)來收集屬性的變化。
    • 將變化的屬性存儲到 this.props 對象中,這樣可以通過 props 屬性訪問組件的所有屬性值。
  4. 保持基類的 willUpdate 方法的調(diào)用

    • 調(diào)用 super.willUpdate(changedProperties) 以確?;惖?willUpdate 方法也能正常執(zhí)行。

代碼詳解

  • 定義了一個默認(rèn)導(dǎo)出的函數(shù),它接受一個構(gòu)造函數(shù) superClass(應(yīng)該是 LitElement 或其子類的構(gòu)造函數(shù))。
  • 創(chuàng)建一個新類 WithPropertiesElement,繼承自 superClass。
  • WithPropertiesElement 類中定義了一個 props 屬性,用于存儲屬性值。
  • 重寫 willUpdate 方法,在組件更新前處理屬性變化,并將變化的屬性存儲到 this.props 中。
  • 返回 WithPropertiesElement 類,并通過類型斷言確保它具有額外的 props 屬性。

使用示例

假設(shè)你有一個基礎(chǔ)的 LitElement 組件:

import { LitElement, html } from 'lit';class MyElement extends LitElement {count = 0;render() {return html`<p>Count: ${this.count}</p>`;}
}customElements.define('my-element', MyElement);

你可以使用這個高階組件來增強(qiáng)它:

import { WithPropertiesElement } from './WithPropertiesElement';
import { LitElement, html } from 'lit';const EnhancedElement = WithPropertiesElement(MyElement);customElements.define('enhanced-element', EnhancedElement);const element = new EnhancedElement();
document.body.appendChild(element);console.log(element.props); // { count: 0 }

在這個示例中,EnhancedElement 繼承自 MyElement 并添加了屬性管理功能。可以通過 element.props 訪問組件的所有屬性值。

這種模式在需要在組件中統(tǒng)一管理屬性或在組件更新前進(jìn)行額外處理時非常有用。

存放React組件的webcomponent基類

重頭戲來了

import { ChildPart, html, PropertyValues } from 'lit'
import { query } from 'lit/decorators.js'
import { Fragment, createElement as h } from 'react'
import ReactDOM from 'react-dom'
import withProperties from '../mixin/withProperties'
import LightBase from './Base'type H = typeof hconst Root: React.FC<any> = props => {return h(Fragment, {...props,})
}const omit = (obj: Record<string, any>, filter: string[] = []) =>Object.fromEntries(Object.entries(obj).filter(([key]) => !filter.includes(key)))// React組件基類
export default class extends withProperties(LightBase) {// 子類要重寫這個方法來渲染自己的組件protected renderReact(h: H): React.ReactNode {return null}protected customContainer(): Element | undefined {return this.$reactRoot}protected getReactProps(props: Record<string, any>) {return omit(props, ['preventCompose', 'preventBubbles', 'localeMessages'])}protected extraStyle = ''@query('.react-root')$reactRoot?: HTMLElementupdated(changed: PropertyValues) {super.updated(changed)this.doRender()}connectedCallback() {super.connectedCallback()// 節(jié)點(diǎn)刪除后重新插入的情形if (this.hasUpdated) {this.doRender()}}disconnectedCallback() {super.disconnectedCallback()this.doUnmount()}private container?: Elementprivate doRender() {const container = this.customContainer()if (!container) {this.doUnmount() // 卸載前一次渲染的內(nèi)容} else {this.container = containerReactDOM.render(h(Root, {}, this.renderReact(h)), container, () => {// hack for error: https://github.com/lit/lit/blob/f8ee010bc515e4bb319e98408d38ef3d971cc08b/packages/lit-html/src/lit-html.ts#L1122// 在React中使用此組件且非首次更新時會報錯,因為lit默認(rèn)會在組件下創(chuàng)建一個注釋節(jié)點(diǎn),更新時會對這個節(jié)點(diǎn)進(jìn)行操作,而React渲染時把這個注釋節(jié)點(diǎn)干掉了,這里要把他加回去const childPart = (this as any).__childPart as ChildPart | undefinedchildPart?.startNode && this.appendChild(childPart.startNode)})}}private doUnmount() {if (this.container) {ReactDOM.unmountComponentAtNode(this.container)}}render() {return html` <div class="react-root"></div> `}
}

使用Demo

import { unsafeCSS } from 'lit'
import { customElement, property } from 'lit/decorators.js'
import ReactBase from './ReactBase'// 自己的React組件
import Component from './Component'import style from './index.less?inline'@customElement('my-diy-react-wc')
export default class DataReport extends ReactBase {static get styles() {return unsafeCSS([style])}/*** 自定義屬性*/@property()language: string = 'zh-CN'// ReactBase中用來渲染React,不要刪除renderReact() {return <Component language={this.language} />}
}

參考文章

https://juejin.cn/post/7296850940404580364?searchId=2024071620331848BC966F0D2051B9C533#heading-9

lit官網(wǎng):https://lit.dev/docs/components/styles/

webcomponent文檔:https://developer.mozilla.org/en-US/docs/Web/API/Web_components

http://www.risenshineclean.com/news/992.html

相關(guān)文章:

  • 網(wǎng)站信息內(nèi)容建設(shè) 宣傳部門游戲優(yōu)化大師
  • 網(wǎng)站開發(fā)高級工程師專業(yè)怎樣申請網(wǎng)站注冊
  • 新聞網(wǎng)站建設(shè)評比規(guī)則2023重大新聞事件10條
  • 網(wǎng)站圖片上的水印怎么做網(wǎng)絡(luò)營銷專業(yè)就業(yè)公司
  • seo擦邊球網(wǎng)站什么廣告推廣最有效果
  • dw用層還是表格做網(wǎng)站快色盲圖
  • 做外貿(mào)哪些網(wǎng)站可以發(fā)免費(fèi)信息大批量刷關(guān)鍵詞排名軟件
  • 海外永久網(wǎng)站百度一下你就知道移動官網(wǎng)
  • 論壇網(wǎng)站開發(fā)外包公司什么意思
  • 網(wǎng)頁游戲人生重開模擬器如何把一個關(guān)鍵詞優(yōu)化到首頁
  • 網(wǎng)站滾動效果怎么做站長工具怎么關(guān)掉
  • 淘寶開放平臺怎么做淘寶客網(wǎng)站網(wǎng)絡(luò)推廣費(fèi)用一般多少
  • 杭州網(wǎng)站建設(shè) 網(wǎng)站設(shè)計安卓優(yōu)化大師app下載安裝
  • 運(yùn)城網(wǎng)站建設(shè)公司有多少錢愛站網(wǎng)seo
  • 邢臺網(wǎng)站建設(shè)要多少錢揚(yáng)州百度關(guān)鍵詞優(yōu)化
  • 境外網(wǎng)站開發(fā)北京it培訓(xùn)機(jī)構(gòu)哪家好
  • 做視頻能賺錢的網(wǎng)站seoheuni
  • 如何注冊公司微信公眾號網(wǎng)站seo系統(tǒng)
  • 國外做建材的網(wǎng)站有哪些手機(jī)端競價惡意點(diǎn)擊能防止嗎
  • 深圳做h5網(wǎng)站設(shè)計百度關(guān)鍵詞排名批量查詢工具
  • 做網(wǎng)站模塊百度一下首頁極簡版
  • 福州網(wǎng)站建設(shè)公司哪家好推廣優(yōu)化師
  • dz網(wǎng)站收款即時到賬怎么做的保定網(wǎng)站建設(shè)報價
  • 貝爾利網(wǎng)站網(wǎng)絡(luò)推廣內(nèi)容
  • 描述建設(shè)一個網(wǎng)站的具體步驟制作網(wǎng)站
  • 開發(fā)一個網(wǎng)站多少錢?上海seo關(guān)鍵詞優(yōu)化
  • 做網(wǎng)站找云無限seo查詢在線
  • 基于ASP與Access數(shù)據(jù)庫的網(wǎng)站開發(fā)東莞網(wǎng)絡(luò)推廣托管
  • 做高效能的父母網(wǎng)站金華seo扣費(fèi)
  • 幫人做網(wǎng)站要怎么賺錢嗎臨沂seo全網(wǎng)營銷