wip: hydrate v-if
This commit is contained in:
parent
b5762b57ae
commit
38d4889de7
|
@ -1,5 +1,5 @@
|
|||
import { createVaporSSRApp, delegateEvents } from '../src'
|
||||
import { nextTick, ref } from '@vue/runtime-dom'
|
||||
import { nextTick, reactive, ref } from '@vue/runtime-dom'
|
||||
import { compileScript, parse } from '@vue/compiler-sfc'
|
||||
import * as runtimeVapor from '../src'
|
||||
import * as runtimeDom from '@vue/runtime-dom'
|
||||
|
@ -50,8 +50,8 @@ function compile(
|
|||
async function testHydration(
|
||||
code: string,
|
||||
components: Record<string, string> = {},
|
||||
data: any = ref('foo'),
|
||||
) {
|
||||
const data = ref('foo')
|
||||
const ssrComponents: any = {}
|
||||
const clientComponents: any = {}
|
||||
for (const key in components) {
|
||||
|
@ -638,7 +638,100 @@ describe('Vapor Mode hydration', () => {
|
|||
)
|
||||
})
|
||||
|
||||
test.todo('if')
|
||||
describe('if', () => {
|
||||
test('basic toggle - true -> false', async () => {
|
||||
const data = ref(true)
|
||||
const { container } = await testHydration(
|
||||
`<template>
|
||||
<div v-if="data">foo</div>
|
||||
</template>`,
|
||||
undefined,
|
||||
data,
|
||||
)
|
||||
expect(container.innerHTML).toMatchInlineSnapshot(
|
||||
`"<div>foo</div><!--if-->"`,
|
||||
)
|
||||
|
||||
data.value = false
|
||||
await nextTick()
|
||||
expect(container.innerHTML).toMatchInlineSnapshot(`"<!--if-->"`)
|
||||
})
|
||||
|
||||
test('basic toggle - false -> true', async () => {
|
||||
const data = ref(false)
|
||||
const { container } = await testHydration(
|
||||
`<template>
|
||||
<div v-if="data">foo</div>
|
||||
</template>`,
|
||||
undefined,
|
||||
data,
|
||||
)
|
||||
expect(container.innerHTML).toMatchInlineSnapshot(`"<!--if-->"`)
|
||||
|
||||
data.value = true
|
||||
await nextTick()
|
||||
expect(container.innerHTML).toMatchInlineSnapshot(
|
||||
`"<div>foo</div><!--if-->"`,
|
||||
)
|
||||
})
|
||||
|
||||
test('v-if/else-if/else chain - switch branches', async () => {
|
||||
const data = ref('a')
|
||||
const { container } = await testHydration(
|
||||
`<template>
|
||||
<div v-if="data === 'a'">foo</div>
|
||||
<div v-else-if="data === 'b'">bar</div>
|
||||
<div v-else>baz</div>
|
||||
</template>`,
|
||||
undefined,
|
||||
data,
|
||||
)
|
||||
expect(container.innerHTML).toMatchInlineSnapshot(
|
||||
`"<div>foo</div><!--if-->"`,
|
||||
)
|
||||
|
||||
data.value = 'b'
|
||||
await nextTick()
|
||||
expect(container.innerHTML).toMatchInlineSnapshot(
|
||||
`"<div>bar</div><!--if--><!--if-->"`,
|
||||
)
|
||||
|
||||
data.value = 'c'
|
||||
await nextTick()
|
||||
expect(container.innerHTML).toMatchInlineSnapshot(
|
||||
`"<div>baz</div><!--if--><!--if-->"`,
|
||||
)
|
||||
})
|
||||
|
||||
test('nested if', async () => {
|
||||
const data = reactive({ outer: true, inner: true })
|
||||
const { container } = await testHydration(
|
||||
`<template>
|
||||
<div v-if="data.outer">
|
||||
<span>outer</span>
|
||||
<div v-if="data.inner">inner</div>
|
||||
</div>
|
||||
</template>`,
|
||||
undefined,
|
||||
data,
|
||||
)
|
||||
expect(container.innerHTML).toMatchInlineSnapshot(
|
||||
`"<div><span>outer</span><div>inner</div><!--if--></div><!--if-->"`,
|
||||
)
|
||||
|
||||
data.inner = false
|
||||
await nextTick()
|
||||
expect(container.innerHTML).toMatchInlineSnapshot(
|
||||
`"<div><span>outer</span><!--if--></div><!--if-->"`,
|
||||
)
|
||||
|
||||
data.outer = false
|
||||
await nextTick()
|
||||
expect(container.innerHTML).toMatchInlineSnapshot(`"<!--if-->"`)
|
||||
})
|
||||
|
||||
test.todo('on component', async () => {})
|
||||
})
|
||||
|
||||
test.todo('for')
|
||||
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
import { type Block, type BlockFn, DynamicFragment, insert } from './block'
|
||||
import { isHydrating, locateHydrationNode } from './dom/hydration'
|
||||
import {
|
||||
currentHydrationNode,
|
||||
isComment,
|
||||
isHydrating,
|
||||
locateHydrationNode,
|
||||
} from './dom/hydration'
|
||||
import { insertionAnchor, insertionParent } from './insertionState'
|
||||
import { renderEffect } from './renderEffect'
|
||||
|
||||
|
@ -11,8 +16,10 @@ export function createIf(
|
|||
): Block {
|
||||
const _insertionParent = insertionParent
|
||||
const _insertionAnchor = insertionAnchor
|
||||
let _currentHydrationNode
|
||||
if (isHydrating) {
|
||||
locateHydrationNode()
|
||||
_currentHydrationNode = currentHydrationNode
|
||||
}
|
||||
|
||||
let frag: Block
|
||||
|
@ -27,5 +34,23 @@ export function createIf(
|
|||
insert(frag, _insertionParent, _insertionAnchor)
|
||||
}
|
||||
|
||||
// if the current hydration node is a comment, use it as an anchor
|
||||
// otherwise need to insert the anchor node
|
||||
// OR adjust ssr output to add anchor for v-if
|
||||
else if (isHydrating && _currentHydrationNode) {
|
||||
const parentNode = _currentHydrationNode.parentNode
|
||||
if (parentNode) {
|
||||
if (isComment(_currentHydrationNode, '')) {
|
||||
if (__DEV__) _currentHydrationNode.data = 'if'
|
||||
;(frag as DynamicFragment).anchor = _currentHydrationNode
|
||||
} else {
|
||||
parentNode.insertBefore(
|
||||
(frag as DynamicFragment).anchor,
|
||||
_currentHydrationNode.nextSibling,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return frag
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue