Skip to content

Commit 8b6b732

Browse files
committed
fix(custom-element): inject child style before parent component's style
1 parent 9fa787c commit 8b6b732

File tree

4 files changed

+53
-5
lines changed

4 files changed

+53
-5
lines changed

packages/runtime-core/src/component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1256,7 +1256,7 @@ export interface ComponentCustomElementInterface {
12561256
/**
12571257
* @internal
12581258
*/
1259-
_injectChildStyle(type: ConcreteComponent): void
1259+
_injectChildStyle(type: ConcreteComponent, parent?: ConcreteComponent): void
12601260
/**
12611261
* @internal
12621262
*/

packages/runtime-core/src/renderer.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1349,7 +1349,8 @@ function baseCreateRenderer(
13491349
} else {
13501350
// custom element style injection
13511351
if (root.ce) {
1352-
root.ce._injectChildStyle(type)
1352+
const parent = instance.parent ? instance.parent.type : undefined
1353+
root.ce._injectChildStyle(type, parent)
13531354
}
13541355

13551356
if (__DEV__) {

packages/runtime-dom/__tests__/customElement.spec.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -916,6 +916,39 @@ describe('defineCustomElement', () => {
916916
assertStyles(el, [`div { color: blue; }`, `div { color: red; }`])
917917
})
918918

919+
test('child components styles should before parent styles', async () => {
920+
const Baz = () => h(Bar)
921+
const Bar = defineComponent({
922+
styles: [`div { color: green; }`],
923+
render() {
924+
return 'bar'
925+
},
926+
})
927+
const WrapperBar = defineComponent({
928+
styles: [`div { color: blue; }`],
929+
render() {
930+
return h(Baz)
931+
},
932+
})
933+
const WBaz = () => h(WrapperBar)
934+
const Foo = defineCustomElement({
935+
styles: [`div { color: red; }`],
936+
render() {
937+
return [h(Baz), h(WBaz)]
938+
},
939+
})
940+
customElements.define('my-el-with-wrapper-child-styles', Foo)
941+
container.innerHTML = `<my-el-with-wrapper-child-styles></my-el-with-wrapper-child-styles>`
942+
const el = container.childNodes[0] as VueElement
943+
944+
// inject order should be child -> parent
945+
assertStyles(el, [
946+
`div { color: green; }`,
947+
`div { color: blue; }`,
948+
`div { color: red; }`,
949+
])
950+
})
951+
919952
test('with nonce', () => {
920953
const Foo = defineCustomElement(
921954
{

packages/runtime-dom/src/apiCustomElement.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ export class VueElement
232232
private _styleChildren = new WeakSet()
233233
private _pendingResolve: Promise<void> | undefined
234234
private _parent: VueElement | undefined
235+
private _styleAnchor?: HTMLStyleElement
235236
/**
236237
* dev only
237238
*/
@@ -584,6 +585,7 @@ export class VueElement
584585
private _applyStyles(
585586
styles: string[] | undefined,
586587
owner?: ConcreteComponent,
588+
parentComp?: ConcreteComponent,
587589
) {
588590
if (!styles) return
589591
if (owner) {
@@ -593,11 +595,20 @@ export class VueElement
593595
this._styleChildren.add(owner)
594596
}
595597
const nonce = this._nonce
598+
let last = undefined
596599
for (let i = styles.length - 1; i >= 0; i--) {
597600
const s = document.createElement('style')
598601
if (nonce) s.setAttribute('nonce', nonce)
599602
s.textContent = styles[i]
600-
this.shadowRoot!.prepend(s)
603+
604+
if (parentComp && this._styleAnchor) {
605+
this.shadowRoot!.insertBefore(s, last || this._styleAnchor)
606+
} else {
607+
this.shadowRoot!.prepend(s)
608+
this._styleAnchor = s
609+
}
610+
last = s
611+
601612
// record for HMR
602613
if (__DEV__) {
603614
if (owner) {
@@ -665,8 +676,11 @@ export class VueElement
665676
/**
666677
* @internal
667678
*/
668-
_injectChildStyle(comp: ConcreteComponent & CustomElementOptions): void {
669-
this._applyStyles(comp.styles, comp)
679+
_injectChildStyle(
680+
comp: ConcreteComponent & CustomElementOptions,
681+
parentComp?: ConcreteComponent,
682+
): void {
683+
this._applyStyles(comp.styles, comp, parentComp)
670684
}
671685

672686
/**

0 commit comments

Comments
 (0)