ITADN
vuejs/core/Issues

Vapor: a declared style prop on a component receives an unmerged array, same bug as #15227 but for style

#15285ClosedMILLERMARRU 创建于 9 天前
scope: vapor
M
MILLERMARRUcommented
#15230 fixed #15227 ("Vapor: class on a component is not normalized, so a declared `class: String` prop receives an Array") by adding a `normalizeRawProp` guard in `packages/runtime-vapor/src/componentProps.ts`: ```ts const normalizeRawProp = (key: string, value: unknown) => key === 'class' && value && !isString(value) ? normalizeClass(value) : value ``` I checked the compiler side (`packages/compiler-vapor/src/transforms/transformElement.ts`, `dedupeProperties`/`mergePropValues`) and it treats `class` and `style` completely symmetrically: when a component receives both a static and a dynamic binding for either (`<Child style="color:red" :style="dynamicObj" />`), both get merged into a raw array (`["color:red", dynamicObj]`). The runtime side mirrors this symmetry too — `getAttrFromRawProps` in the same `componentProps.ts` file explicitly special-cases `key === 'class' || key === 'style'` together for the fallthrough-attrs merge path (with the comment "need special merging behavior for class & style"). But `normalizeRawProp`, used when a component explicitly *declares* the prop (e.g. `defineProps({ style: Object })`), only unwraps `class` — there's no `key === 'style'` branch, and `normalizeStyle` isn't imported into this resolution path at all. So a declared `style` prop receives the raw unmerged array instead of the merged object/string VDOM would produce via `normalizeStyle` (`packages/runtime-core/src/vnode.ts`, `props.style = normalizeStyle(style)`). ### Reproduction ```vue <!-- Child.vue --> <script setup vapor> defineProps<{ style?: any }>() </script> <template> <pre>{{ JSON.stringify(style) }}</pre> </template> <!-- Parent.vue --> <script setup vapor> import Child from './Child.vue' const dynamicStyle = { color: 'red' } </script> <template> <Child style="font-weight:bold" :style="dynamicStyle" /> </template> ``` Expected (matches VDOM): `style` resolves to a merged object/string. Actual in Vapor: `style` is the raw array `["font-weight:bold", { color: "red" }]`.
关闭于 9 天前 2 条评论