fix(runtime-vapor): dynamic component attrs fallthrough (#13466)

This commit is contained in:
edison 2025-06-20 08:40:52 +08:00 committed by GitHub
parent d65675d902
commit 6f6ab1ab3c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 65 additions and 9 deletions

View File

@ -8,6 +8,8 @@ import {
} from '@vue/runtime-dom'
import {
createComponent,
createDynamicComponent,
createSlot,
defineVaporComponent,
renderEffect,
setClass,
@ -285,7 +287,43 @@ describe('attribute fallthrough', () => {
expect(getCSS()).not.toContain('font-size:bold')
})
test('parent value should take priority', async () => {
it('should fallthrough attrs to dynamic component', async () => {
const Comp = defineVaporComponent({
setup() {
const n1 = createDynamicComponent(
() => 'button',
null,
{
default: () => {
const n0 = createSlot('default', null)
return n0
},
},
true,
)
return n1
},
})
const { html } = define({
setup() {
return createComponent(
Comp,
{
class: () => 'foo',
},
null,
true,
)
},
}).render()
expect(html()).toBe(
'<button class="foo"><!--slot--></button><!--dynamic-component-->',
)
})
it('parent value should take priority', async () => {
const parentVal = ref('parent')
const childVal = ref('child')

View File

@ -25,7 +25,7 @@ import {
unregisterHMR,
warn,
} from '@vue/runtime-dom'
import { type Block, insert, isBlock, remove } from './block'
import { type Block, DynamicFragment, insert, isBlock, remove } from './block'
import {
type ShallowRef,
markRaw,
@ -255,14 +255,16 @@ export function createComponent(
if (
instance.hasFallthrough &&
component.inheritAttrs !== false &&
instance.block instanceof Element &&
Object.keys(instance.attrs).length
) {
renderEffect(() => {
isApplyingFallthroughProps = true
setDynamicProps(instance.block as Element, [instance.attrs])
isApplyingFallthroughProps = false
})
const el = getRootElement(instance)
if (el) {
renderEffect(() => {
isApplyingFallthroughProps = true
setDynamicProps(el, [instance.attrs])
isApplyingFallthroughProps = false
})
}
}
resetTracking()
@ -563,3 +565,18 @@ export function getExposed(
)
}
}
function getRootElement({
block,
}: VaporComponentInstance): Element | undefined {
if (block instanceof Element) {
return block
}
if (block instanceof DynamicFragment) {
const { nodes } = block
if (nodes instanceof Element && (nodes as any).$root) {
return nodes
}
}
}

View File

@ -210,7 +210,8 @@ export function hasAttrFromRawProps(rawProps: RawProps, key: string): boolean {
if (dynamicSources) {
let i = dynamicSources.length
while (i--) {
if (hasOwn(resolveSource(dynamicSources[i]), key)) {
const source = resolveSource(dynamicSources[i])
if (source && hasOwn(source, key)) {
return true
}
}