Skip to content
This repository was archived by the owner on Jul 19, 2025. It is now read-only.

Commit 7f3ca46

Browse files
committed
fix(runtime-vapor): scope id for v-if
1 parent faa3e2c commit 7f3ca46

File tree

4 files changed

+37
-37
lines changed

4 files changed

+37
-37
lines changed

packages/runtime-vapor/src/apiCreateComponent.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ export function createComponent(
3838
slots,
3939
once,
4040
)
41+
42+
instance.scopeIds = [...current.scopeIds]
43+
const scopeId = current.type.__scopeId
44+
if (scopeId) instance.scopeIds.push(scopeId)
45+
4146
setupComponent(instance)
4247

4348
// register sub-component with current component for lifecycle management

packages/runtime-vapor/src/apiRender.ts

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,17 @@ export function setupComponent(instance: ComponentInternalInstance): void {
9191
block = []
9292
}
9393
instance.block = block
94-
fallThroughAttrs(instance)
95-
attachScopeId(instance)
94+
95+
const rootElement = findFirstRootElement(instance)
96+
if (rootElement) {
97+
fallThroughAttrs(instance, rootElement)
98+
99+
// attach scopeId
100+
for (const id of instance.scopeIds) {
101+
rootElement.setAttribute(id, '')
102+
}
103+
}
104+
96105
return block
97106
})
98107
reset()
@@ -168,15 +177,19 @@ export function unmountComponent(instance: ComponentInternalInstance): void {
168177
flushPostFlushCbs()
169178
}
170179

171-
export function attachScopeId(instance: ComponentInternalInstance): void {
172-
const scopeId = instance.type.__scopeId
173-
if (scopeId) {
174-
let blk: Block | null = instance.block
175-
while (blk && componentKey in blk) {
176-
blk = blk.block
177-
if (blk instanceof Element) {
178-
blk.setAttribute(scopeId, '')
179-
}
180+
function findFirstRootElement(instance: ComponentInternalInstance) {
181+
const element = getFirstNode(instance.block)
182+
return element instanceof Element ? element : undefined
183+
}
184+
185+
function getFirstNode(block: Block | null): Node | undefined {
186+
if (!block || componentKey in block) return
187+
if (block instanceof Node) return block
188+
if (isArray(block)) {
189+
if (block.length === 1) {
190+
return getFirstNode(block[0])
180191
}
192+
} else {
193+
return getFirstNode(block.nodes)
181194
}
182195
}

packages/runtime-vapor/src/component.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ export interface ComponentInternalInstance {
162162
provides: Data
163163
scope: EffectScope
164164
comps: Set<ComponentInternalInstance>
165+
scopeIds: string[]
165166

166167
rawProps: NormalizedRawProps
167168
propsOptions: NormalizedPropsOptions
@@ -293,6 +294,7 @@ export function createComponentInstance(
293294
provides: parent ? parent.provides : Object.create(_appContext.provides),
294295
type: component,
295296
comps: new Set(),
297+
scopeIds: [],
296298

297299
// resolved props and emits options
298300
rawProps: null!, // set later

packages/runtime-vapor/src/componentAttrs.ts

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
import { camelize, isArray, normalizeClass, normalizeStyle } from '@vue/shared'
2-
import {
3-
type ComponentInternalInstance,
4-
componentKey,
5-
currentInstance,
6-
} from './component'
2+
import { type ComponentInternalInstance, currentInstance } from './component'
73
import { isEmitListener } from './componentEmits'
84
import { type RawProps, walkRawProps } from './componentProps'
95
import { renderEffect } from './renderEffect'
106
import { mergeProp, setDynamicProp } from './dom/prop'
11-
import type { Block } from './apiRender'
127

138
export function patchAttrs(
149
instance: ComponentInternalInstance,
@@ -97,35 +92,20 @@ export function withAttrs(props: RawProps): RawProps {
9792
return [attrsGetter, props]
9893
}
9994

100-
function getFirstNode(block: Block | undefined): Node | undefined {
101-
if (!block || componentKey in block) return
102-
if (block instanceof Node) return block
103-
if (isArray(block)) {
104-
if (block.length === 1) {
105-
return getFirstNode(block[0])
106-
}
107-
} else {
108-
return getFirstNode(block.nodes)
109-
}
110-
}
111-
112-
export function fallThroughAttrs(instance: ComponentInternalInstance): void {
95+
export function fallThroughAttrs(
96+
instance: ComponentInternalInstance,
97+
element: Element,
98+
): void {
11399
const {
114-
block,
115100
type: { inheritAttrs },
116101
dynamicAttrs,
117102
} = instance
118103
if (
119104
inheritAttrs === false ||
120-
dynamicAttrs === true || // all props as dynamic
121-
!block ||
122-
componentKey in block
105+
dynamicAttrs === true // all props as dynamic
123106
)
124107
return
125108

126-
const element = getFirstNode(block)
127-
if (!element || !(element instanceof Element)) return
128-
129109
const hasStaticAttrs = dynamicAttrs || dynamicAttrs === false
130110

131111
let initial: Record<string, string> | undefined

0 commit comments

Comments
 (0)