mirror of https://github.com/vuejs/core.git
fix(runtime-vapor): `v-if` with inherit attrs
This commit is contained in:
parent
7a98f4b565
commit
faa3e2c0d2
|
@ -45,14 +45,15 @@ export function render(_ctx) {
|
|||
`;
|
||||
|
||||
exports[`compiler: v-for > multi effect 1`] = `
|
||||
"import { renderEffect as _renderEffect, setDynamicProp as _setDynamicProp, createFor as _createFor, template as _template } from 'vue/vapor';
|
||||
"import { setInheritAttrs as _setInheritAttrs, renderEffect as _renderEffect, setDynamicProp as _setDynamicProp, createFor as _createFor, template as _template } from 'vue/vapor';
|
||||
const t0 = _template("<div></div>")
|
||||
|
||||
export function render(_ctx) {
|
||||
const n0 = _createFor(() => (_ctx.items), (_ctx0) => {
|
||||
const n2 = t0()
|
||||
_renderEffect(() => _setDynamicProp(n2, "item", _ctx0[0].value))
|
||||
_renderEffect(() => _setDynamicProp(n2, "index", _ctx0[1].value))
|
||||
_setInheritAttrs(["item", "index"])
|
||||
_renderEffect(() => _setDynamicProp(n2, "item", _ctx0[0].value, true))
|
||||
_renderEffect(() => _setDynamicProp(n2, "index", _ctx0[1].value, true))
|
||||
return n2
|
||||
})
|
||||
return n0
|
||||
|
|
|
@ -92,6 +92,7 @@ describe('compiler: template ref transform', () => {
|
|||
|
||||
const { positive } = ir.block.operation[0] as IfIRNode
|
||||
expect(positive.operation).toMatchObject([
|
||||
{ type: IRNodeTypes.SET_INHERIT_ATTRS },
|
||||
{
|
||||
type: IRNodeTypes.SET_TEMPLATE_REF,
|
||||
element: 2,
|
||||
|
@ -113,6 +114,7 @@ describe('compiler: template ref transform', () => {
|
|||
|
||||
const { render } = ir.block.operation[0] as ForIRNode
|
||||
expect(render.operation).toMatchObject([
|
||||
{ type: IRNodeTypes.SET_INHERIT_ATTRS },
|
||||
{
|
||||
type: IRNodeTypes.SET_TEMPLATE_REF,
|
||||
element: 2,
|
||||
|
|
|
@ -64,11 +64,20 @@ export const transformElement: NodeTransform = (node, context) => {
|
|||
isDynamicComponent,
|
||||
)
|
||||
|
||||
let { parent } = context
|
||||
while (
|
||||
parent &&
|
||||
parent.parent &&
|
||||
parent.node.type === NodeTypes.ELEMENT &&
|
||||
parent.node.tagType === ElementTypes.TEMPLATE
|
||||
) {
|
||||
parent = parent.parent
|
||||
}
|
||||
const singleRoot =
|
||||
context.root === context.parent &&
|
||||
context.parent.node.children.filter(
|
||||
child => child.type !== NodeTypes.COMMENT,
|
||||
).length === 1
|
||||
context.root === parent &&
|
||||
parent.node.children.filter(child => child.type !== NodeTypes.COMMENT)
|
||||
.length === 1
|
||||
|
||||
;(isComponent ? transformComponentElement : transformNativeElement)(
|
||||
node as any,
|
||||
propsResult,
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
import { camelize, isArray, normalizeClass, normalizeStyle } from '@vue/shared'
|
||||
import { type ComponentInternalInstance, currentInstance } from './component'
|
||||
import {
|
||||
type ComponentInternalInstance,
|
||||
componentKey,
|
||||
currentInstance,
|
||||
} from './component'
|
||||
import { isEmitListener } from './componentEmits'
|
||||
import { type RawProps, walkRawProps } from './componentProps'
|
||||
import { renderEffect } from './renderEffect'
|
||||
import { mergeProp, setDynamicProp } from './dom/prop'
|
||||
import type { Block } from './apiRender'
|
||||
|
||||
export function patchAttrs(
|
||||
instance: ComponentInternalInstance,
|
||||
|
@ -92,6 +97,18 @@ export function withAttrs(props: RawProps): RawProps {
|
|||
return [attrsGetter, props]
|
||||
}
|
||||
|
||||
function getFirstNode(block: Block | undefined): Node | undefined {
|
||||
if (!block || componentKey in block) return
|
||||
if (block instanceof Node) return block
|
||||
if (isArray(block)) {
|
||||
if (block.length === 1) {
|
||||
return getFirstNode(block[0])
|
||||
}
|
||||
} else {
|
||||
return getFirstNode(block.nodes)
|
||||
}
|
||||
}
|
||||
|
||||
export function fallThroughAttrs(instance: ComponentInternalInstance): void {
|
||||
const {
|
||||
block,
|
||||
|
@ -100,20 +117,23 @@ export function fallThroughAttrs(instance: ComponentInternalInstance): void {
|
|||
} = instance
|
||||
if (
|
||||
inheritAttrs === false ||
|
||||
!(block instanceof Element) ||
|
||||
// all props as dynamic
|
||||
dynamicAttrs === true
|
||||
dynamicAttrs === true || // all props as dynamic
|
||||
!block ||
|
||||
componentKey in block
|
||||
)
|
||||
return
|
||||
|
||||
const element = getFirstNode(block)
|
||||
if (!element || !(element instanceof Element)) return
|
||||
|
||||
const hasStaticAttrs = dynamicAttrs || dynamicAttrs === false
|
||||
|
||||
let initial: Record<string, string> | undefined
|
||||
if (hasStaticAttrs) {
|
||||
// attrs in static template
|
||||
initial = {}
|
||||
for (let i = 0; i < block.attributes.length; i++) {
|
||||
const attr = block.attributes[i]
|
||||
for (let i = 0; i < element.attributes.length; i++) {
|
||||
const attr = element.attributes[i]
|
||||
if (dynamicAttrs && dynamicAttrs.includes(attr.name)) continue
|
||||
initial[attr.name] = attr.value
|
||||
}
|
||||
|
@ -124,13 +144,13 @@ export function fallThroughAttrs(instance: ComponentInternalInstance): void {
|
|||
if (dynamicAttrs && dynamicAttrs.includes(key)) continue
|
||||
|
||||
let value: unknown
|
||||
if (hasStaticAttrs) {
|
||||
if (hasStaticAttrs && key in initial!) {
|
||||
value = mergeProp(key, instance.attrs[key], initial![key])
|
||||
} else {
|
||||
value = instance.attrs[key]
|
||||
}
|
||||
|
||||
setDynamicProp(block, key, value)
|
||||
setDynamicProp(element, key, value)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue