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