mirror of https://github.com/vuejs/core.git
wip(vapor): createIf
This commit is contained in:
parent
bcb9209c4c
commit
4318129b96
|
@ -169,10 +169,12 @@ describe('component: slots', () => {
|
|||
})
|
||||
|
||||
test('slot should be rendered correctly with slot props', async () => {
|
||||
const src = ref('header')
|
||||
|
||||
const Comp = defineVaporComponent(() => {
|
||||
const n0 = template('<div></div>')()
|
||||
insert(
|
||||
createSlot('header', { title: () => 'header' }),
|
||||
createSlot('header', { title: () => src.value }),
|
||||
n0 as any as ParentNode,
|
||||
)
|
||||
return n0
|
||||
|
@ -191,6 +193,10 @@ describe('component: slots', () => {
|
|||
}).render()
|
||||
|
||||
expect(host.innerHTML).toBe('<div><h1>header</h1><!--slot--></div>')
|
||||
|
||||
src.value = 'footer'
|
||||
await nextTick()
|
||||
expect(host.innerHTML).toBe('<div><h1>footer</h1><!--slot--></div>')
|
||||
})
|
||||
|
||||
test('dynamic slot props', async () => {
|
||||
|
@ -263,17 +269,23 @@ describe('component: slots', () => {
|
|||
$: [
|
||||
() => ({
|
||||
name: 'header',
|
||||
fn: (props: any) => template(props.title)(),
|
||||
fn: (props: any) => {
|
||||
const el = template('<h1></h1>')()
|
||||
renderEffect(() => {
|
||||
setText(el, props.title)
|
||||
})
|
||||
return el
|
||||
},
|
||||
}),
|
||||
],
|
||||
})
|
||||
}).render()
|
||||
|
||||
expect(host.innerHTML).toBe('<div>header<!--slot--></div>')
|
||||
expect(host.innerHTML).toBe('<div><h1>header</h1><!--slot--></div>')
|
||||
|
||||
val.value = 'footer'
|
||||
await nextTick()
|
||||
expect(host.innerHTML).toBe('<div>footer<!--slot--></div>')
|
||||
expect(host.innerHTML).toBe('<div><h1>footer</h1><!--slot--></div>')
|
||||
})
|
||||
|
||||
test('dynamic slot outlet should be render correctly with slot props', async () => {
|
||||
|
|
|
@ -15,7 +15,7 @@ import { unmountComponent } from '../src/component'
|
|||
|
||||
const define = makeRender()
|
||||
|
||||
describe.todo('createIf', () => {
|
||||
describe('createIf', () => {
|
||||
test('basic', async () => {
|
||||
// mock this template:
|
||||
// <div>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import type { BlockFn, Fragment } from './block'
|
||||
import { type BlockFn, DynamicFragment } from './block'
|
||||
import { renderEffect } from './renderEffect'
|
||||
|
||||
export function createIf(
|
||||
condition: () => any,
|
||||
|
@ -6,6 +7,12 @@ export function createIf(
|
|||
b2?: BlockFn,
|
||||
once?: boolean,
|
||||
// hydrationNode?: Node,
|
||||
): Fragment {
|
||||
return [] as any
|
||||
): DynamicFragment {
|
||||
const frag = __DEV__ ? new DynamicFragment('if') : new DynamicFragment()
|
||||
if (once) {
|
||||
frag.update(condition() ? b1 : b2)
|
||||
} else {
|
||||
renderEffect(() => frag.update(condition() ? b1 : b2))
|
||||
}
|
||||
return frag
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import {
|
|||
unmountComponent,
|
||||
} from './component'
|
||||
import { createComment } from './dom/node'
|
||||
import { EffectScope } from '@vue/reactivity'
|
||||
import { EffectScope, pauseTracking, resetTracking } from '@vue/reactivity'
|
||||
|
||||
export type Block =
|
||||
| Node
|
||||
|
@ -29,7 +29,7 @@ export class Fragment {
|
|||
export class DynamicFragment extends Fragment {
|
||||
anchor: Node
|
||||
scope: EffectScope | undefined
|
||||
key: any
|
||||
current?: BlockFn
|
||||
|
||||
constructor(anchorLabel?: string) {
|
||||
super([])
|
||||
|
@ -40,10 +40,13 @@ export class DynamicFragment extends Fragment {
|
|||
document.createTextNode('')
|
||||
}
|
||||
|
||||
update(render?: BlockFn, key: any = render): void {
|
||||
if (key === this.key) return
|
||||
this.key = key
|
||||
update(render?: BlockFn): void {
|
||||
if (render === this.current) {
|
||||
return
|
||||
}
|
||||
this.current = render
|
||||
|
||||
pauseTracking()
|
||||
const parent = this.anchor.parentNode
|
||||
|
||||
// teardown previous branch
|
||||
|
@ -60,6 +63,7 @@ export class DynamicFragment extends Fragment {
|
|||
this.scope = undefined
|
||||
this.nodes = []
|
||||
}
|
||||
resetTracking()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -109,26 +109,28 @@ export function createSlot(
|
|||
fallback?: Slot,
|
||||
): Block {
|
||||
const instance = currentInstance as VaporComponentInstance
|
||||
const fragment = new DynamicFragment('slot')
|
||||
const rawSlots = instance.rawSlots
|
||||
const isDynamicName = isFunction(name)
|
||||
const fragment = __DEV__ ? new DynamicFragment('slot') : new DynamicFragment()
|
||||
const slotProps = rawProps
|
||||
? new Proxy(rawProps, dynamicSlotsPropsProxyHandlers)
|
||||
: EMPTY_OBJ
|
||||
|
||||
// always create effect because a slot may contain dynamic root inside
|
||||
// which affects fallback
|
||||
renderEffect(() => {
|
||||
const slot = getSlot(instance.rawSlots, isFunction(name) ? name() : name)
|
||||
const renderSlot = (name: string) => {
|
||||
const slot = getSlot(rawSlots, name)
|
||||
if (slot) {
|
||||
fragment.update(
|
||||
() => slot(slotProps) || (fallback && fallback()),
|
||||
// TODO this key needs to account for possible fallback (v-if)
|
||||
// inside the slot
|
||||
slot,
|
||||
)
|
||||
fragment.update(() => slot(slotProps) || (fallback && fallback()))
|
||||
} else {
|
||||
fragment.update(fallback)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// dynamic slot name or has dynamicSlots
|
||||
if (isDynamicName || rawSlots.$) {
|
||||
renderEffect(() => renderSlot(isFunction(name) ? name() : name))
|
||||
} else {
|
||||
renderSlot(name)
|
||||
}
|
||||
|
||||
return fragment
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue