From 41379c4d9582acb183ccda82ffe0105b8312a307 Mon Sep 17 00:00:00 2001 From: daiwei Date: Fri, 23 May 2025 17:34:52 +0800 Subject: [PATCH] wip: save --- .../__tests__/customElement.spec.ts | 43 +++++++++++++++++++ packages/runtime-dom/src/apiCustomElement.ts | 21 ++++++--- 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/packages/runtime-dom/__tests__/customElement.spec.ts b/packages/runtime-dom/__tests__/customElement.spec.ts index 09d4b0bdee..23d5ffed0f 100644 --- a/packages/runtime-dom/__tests__/customElement.spec.ts +++ b/packages/runtime-dom/__tests__/customElement.spec.ts @@ -977,6 +977,49 @@ describe('defineCustomElement', () => { assertStyles(el, [`div { color: green; }`, `div { color: blue; }`]) }) + test('inject nested child component styles', async () => { + const Baz = defineComponent({ + styles: [`div { color: yellow; }`], + render() { + return h(Bar) + }, + }) + const Bar = defineComponent({ + styles: [`div { color: green; }`], + render() { + return 'bar' + }, + }) + const WrapperBar = defineComponent({ + styles: [`div { color: blue; }`], + render() { + return h(Baz) + }, + }) + const WBaz = defineComponent({ + styles: [`div { color: black; }`], + render() { + return h(WrapperBar) + }, + }) + const Foo = defineCustomElement({ + styles: [`div { color: red; }`], + render() { + return [h(Baz), h(WBaz)] + }, + }) + customElements.define('my-el-with-inject-nested-child-styles', Foo) + container.innerHTML = `` + const el = container.childNodes[0] as VueElement + assertStyles(el, [ + `div { color: green; }`, + `div { color: yellow; }`, + `div { color: blue; }`, + `div { color: black; }`, + `div { color: red; }`, + ]) + }) + test('with nonce', () => { const Foo = defineCustomElement( { diff --git a/packages/runtime-dom/src/apiCustomElement.ts b/packages/runtime-dom/src/apiCustomElement.ts index 15b3c33d87..5de32735fd 100644 --- a/packages/runtime-dom/src/apiCustomElement.ts +++ b/packages/runtime-dom/src/apiCustomElement.ts @@ -232,7 +232,8 @@ export class VueElement private _styleChildren = new WeakSet() private _pendingResolve: Promise | undefined private _parent: VueElement | undefined - private _styleAnchor?: HTMLStyleElement | Text + private _styleAnchors: WeakMap = + new WeakMap() /** * dev only */ @@ -599,12 +600,13 @@ export class VueElement // to inject child styles before it. if (parentComp && !parentComp.styles) { const anchor = document.createTextNode('') - if (this._styleAnchor) { - this.shadowRoot!.insertBefore(anchor, this._styleAnchor) + const styleAnchor = this._styleAnchors.get(this._def) + if (styleAnchor) { + this.shadowRoot!.insertBefore(anchor, styleAnchor) } else { this.shadowRoot!.prepend(anchor) } - this._styleAnchor = anchor + this._styleAnchors.set(this._def, anchor) } const nonce = this._nonce @@ -616,12 +618,19 @@ export class VueElement // inject styles before parent styles if (parentComp) { - this.shadowRoot!.insertBefore(s, last || this._styleAnchor!) + this.shadowRoot!.insertBefore( + s, + last || + this._styleAnchors.get(parentComp) || + this._styleAnchors.get(this._def) || + null, + ) } else { this.shadowRoot!.prepend(s) - this._styleAnchor = s + this._styleAnchors.set(this._def, s) } last = s + if (owner && i === 0) this._styleAnchors.set(owner, s) // record for HMR if (__DEV__) { -- 2.47.2