mirror of https://github.com/vuejs/core.git
feat(hydration): handle consecutive if node
This commit is contained in:
parent
5ee1628687
commit
85693f0eb3
|
@ -1269,6 +1269,26 @@ describe('Vapor Mode hydration', () => {
|
|||
expect(container.innerHTML).toBe(`<!--${anchorLabel}-->`)
|
||||
})
|
||||
|
||||
test('consecutive if node', async () => {
|
||||
const data = ref(true)
|
||||
const { container } = await testHydration(
|
||||
`<template>
|
||||
<components.Child v-if="data"/>
|
||||
</template>`,
|
||||
{ Child: `<template><div v-if="data">foo</div></template>` },
|
||||
data,
|
||||
)
|
||||
expect(container.innerHTML).toBe(`<div>foo</div><!--if--><!--if-->`)
|
||||
|
||||
data.value = false
|
||||
await nextTick()
|
||||
expect(container.innerHTML).toBe(`<!--if-->`)
|
||||
|
||||
data.value = true
|
||||
await nextTick()
|
||||
expect(container.innerHTML).toBe(`<div>foo</div><!--if--><!--if-->`)
|
||||
})
|
||||
|
||||
test('v-if/else-if/else chain on component - switch branches', async () => {
|
||||
const data = ref('a')
|
||||
const { container } = await testHydration(
|
||||
|
|
|
@ -8,6 +8,7 @@ import {
|
|||
import { createComment, createTextNode } from './dom/node'
|
||||
import { EffectScope, setActiveSub } from '@vue/reactivity'
|
||||
import {
|
||||
advanceHydrationNode,
|
||||
currentHydrationNode,
|
||||
isComment,
|
||||
isHydrating,
|
||||
|
@ -41,12 +42,13 @@ export class DynamicFragment extends VaporFragment {
|
|||
current?: BlockFn
|
||||
fallback?: BlockFn
|
||||
teardown?: () => void
|
||||
anchorLabel?: string
|
||||
|
||||
constructor(anchorLabel?: string) {
|
||||
super([])
|
||||
if (isHydrating) {
|
||||
this.anchorLabel = anchorLabel
|
||||
locateHydrationNode()
|
||||
this.hydrate(anchorLabel!)
|
||||
} else {
|
||||
this.anchor =
|
||||
__DEV__ && anchorLabel ? createComment(anchorLabel) : createTextNode()
|
||||
|
@ -55,12 +57,13 @@ export class DynamicFragment extends VaporFragment {
|
|||
|
||||
update(render?: BlockFn, key: any = render): void {
|
||||
if (key === this.current) {
|
||||
if (isHydrating) this.hydrate(this.anchorLabel!)
|
||||
return
|
||||
}
|
||||
this.current = key
|
||||
|
||||
const prevSub = setActiveSub()
|
||||
const parent = this.anchor.parentNode
|
||||
const parent = isHydrating ? null : this.anchor.parentNode
|
||||
|
||||
// teardown previous branch
|
||||
if (this.scope) {
|
||||
|
@ -89,6 +92,8 @@ export class DynamicFragment extends VaporFragment {
|
|||
}
|
||||
|
||||
setActiveSub(prevSub)
|
||||
|
||||
if (isHydrating) this.hydrate(this.anchorLabel!)
|
||||
}
|
||||
|
||||
hydrate(label: string): void {
|
||||
|
@ -105,6 +110,7 @@ export class DynamicFragment extends VaporFragment {
|
|||
throw new Error(`${label} fragment anchor node was not found.`)
|
||||
}
|
||||
}
|
||||
advanceHydrationNode(this.anchor)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,10 @@ export function setCurrentHydrationNode(node: Node | null): void {
|
|||
currentHydrationNode = node
|
||||
}
|
||||
|
||||
export function advanceHydrationNode(node: Node): void {
|
||||
setCurrentHydrationNode(node.nextSibling || node.parentNode)
|
||||
}
|
||||
|
||||
let isOptimized = false
|
||||
|
||||
function performHydration<T>(
|
||||
|
@ -96,7 +100,7 @@ function adoptTemplateImpl(node: Node, template: string): Node | null {
|
|||
}
|
||||
}
|
||||
|
||||
currentHydrationNode = node.nextSibling
|
||||
advanceHydrationNode(node)
|
||||
return node
|
||||
}
|
||||
|
||||
|
@ -169,12 +173,12 @@ export function isNonHydrationNode(node: Node): boolean {
|
|||
export function locateVaporFragmentAnchor(
|
||||
node: Node,
|
||||
anchorLabel: string,
|
||||
): Comment | undefined {
|
||||
let n = node.nextSibling
|
||||
while (n) {
|
||||
if (isComment(n, anchorLabel)) return n
|
||||
n = n.nextSibling
|
||||
): Comment | null {
|
||||
while (node) {
|
||||
if (isComment(node, anchorLabel)) return node
|
||||
node = node.nextSibling!
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
export function isEmptyTextNode(node: Node): node is Text {
|
||||
|
|
Loading…
Reference in New Issue