Skip to content

Commit aec4002

Browse files
committed
wip: style mismatch with v-show
1 parent 8f23b4e commit aec4002

File tree

3 files changed

+65
-16
lines changed

3 files changed

+65
-16
lines changed

packages/runtime-vapor/__tests__/hydration.spec.ts

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3220,19 +3220,35 @@ describe('Vapor Mode hydration', () => {
32203220
expect(`Hydration style mismatch`).toHaveBeenWarnedTimes(1)
32213221
})
32223222

3223-
test.todo('style mismatch w/ v-show', () => {
3224-
// mountWithHydration(`<div style="color:red;display:none"></div>`, () =>
3225-
// withDirectives(createVNode('div', { style: 'color: red' }, ''), [
3226-
// [vShow, false],
3227-
// ]),
3228-
// )
3229-
// expect(`Hydration style mismatch`).not.toHaveBeenWarned()
3230-
// mountWithHydration(`<div style="color:red;"></div>`, () =>
3231-
// withDirectives(createVNode('div', { style: 'color: red' }, ''), [
3232-
// [vShow, false],
3233-
// ]),
3234-
// )
3235-
// expect(`Hydration style mismatch`).toHaveBeenWarnedTimes(1)
3223+
test('style mismatch w/ v-show', async () => {
3224+
await mountWithHydration(
3225+
`<div style="color:red;display:none"></div>`,
3226+
`<div v-show="data" style="color: red;"></div>`,
3227+
ref(false),
3228+
)
3229+
expect(`Hydration style mismatch`).not.toHaveBeenWarned()
3230+
3231+
// mismatch with single root
3232+
const { container: root } = await mountWithHydration(
3233+
`<div style="color:red;"></div>`,
3234+
`<div v-show="data" style="color: red;"></div>`,
3235+
ref(false),
3236+
)
3237+
expect(root.innerHTML).toBe(
3238+
'<div style="color: red; display: none;"></div>',
3239+
)
3240+
expect(`Hydration style mismatch`).toHaveBeenWarned()
3241+
3242+
// mismatch with multiple root
3243+
const { container } = await mountWithHydration(
3244+
`<div style="color:red;"></div><span/>`,
3245+
`<div v-show="data.show" :style="data.style"></div><span/>`,
3246+
ref({ show: false, style: 'color: red' }),
3247+
)
3248+
expect(container.innerHTML).toBe(
3249+
'<div style="color: red; display: none;"></div><span></span>',
3250+
)
3251+
expect(`Hydration style mismatch`).toHaveBeenWarned()
32363252
})
32373253

32383254
// test('attr mismatch', () => {

packages/runtime-vapor/src/directives/vShow.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import {
2+
MismatchTypes,
23
type VShowElement,
34
vShowHidden,
45
vShowOriginalDisplay,
56
warn,
7+
warnPropMismatch,
68
} from '@vue/runtime-dom'
79
import { renderEffect } from '../renderEffect'
810
import { isVaporComponent } from '../component'
911
import { type Block, DynamicFragment } from '../block'
1012
import { isArray } from '@vue/shared'
13+
import { isHydrating, logMismatchError } from '../dom/hydration'
1114

1215
export function applyVShow(target: Block, source: () => any): void {
1316
if (isVaporComponent(target)) {
@@ -45,7 +48,28 @@ function setDisplay(target: Block, value: unknown): void {
4548
el[vShowOriginalDisplay] =
4649
el.style.display === 'none' ? '' : el.style.display
4750
}
48-
el.style.display = value ? el[vShowOriginalDisplay]! : 'none'
51+
52+
if (
53+
(__DEV__ || __FEATURE_PROD_HYDRATION_MISMATCH_DETAILS__) &&
54+
isHydrating
55+
) {
56+
if (!value && el.style.display !== 'none') {
57+
warnPropMismatch(
58+
el,
59+
'style',
60+
MismatchTypes.STYLE,
61+
`display: ${el.style.display}`,
62+
'display: none',
63+
)
64+
logMismatchError()
65+
66+
el.style.display = 'none'
67+
el[vShowOriginalDisplay] = ''
68+
}
69+
} else {
70+
el.style.display = value ? el[vShowOriginalDisplay]! : 'none'
71+
}
72+
4973
el[vShowHidden] = !value
5074
} else if (__DEV__) {
5175
warn(

packages/runtime-vapor/src/dom/prop.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
shouldSetAsProp,
2222
toClassSet,
2323
toStyleMap,
24+
vShowHidden,
2425
warn,
2526
warnPropMismatch,
2627
} from '@vue/runtime-dom'
@@ -201,7 +202,11 @@ export function setStyle(el: TargetElement, value: any): void {
201202
const expected = stringifyStyle(normalizedValue)
202203
const expectedStyleMap = toStyleMap(expected)
203204

204-
// TODO: handle v-show="false"
205+
// If `v-show=false`, `display: 'none'` should be added to expected
206+
if ((el as any)[vShowHidden]) {
207+
expectedStyleMap.set('display', 'none')
208+
}
209+
205210
// TODO: handle css vars
206211

207212
if (!isMapEqual(actualStyleMap, expectedStyleMap)) {
@@ -228,7 +233,11 @@ function setStyleIncremental(el: any, value: any): NormalizedStyle | undefined {
228233
const expected = isString(value) ? value : stringifyStyle(normalizedValue)
229234
const expectedStyleMap = toStyleMap(expected)
230235

231-
// TODO: handle v-show="false"
236+
// If `v-show=false`, `display: 'none'` should be added to expected
237+
if (el[vShowHidden]) {
238+
expectedStyleMap.set('display', 'none')
239+
}
240+
232241
// TODO: handle css vars
233242

234243
// check if the expected styles are present in the actual styles

0 commit comments

Comments
 (0)