Skip to content

Commit 4318129

Browse files
committed
wip(vapor): createIf
1 parent bcb9209 commit 4318129

File tree

5 files changed

+50
-25
lines changed

5 files changed

+50
-25
lines changed

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

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -169,10 +169,12 @@ describe('component: slots', () => {
169169
})
170170

171171
test('slot should be rendered correctly with slot props', async () => {
172+
const src = ref('header')
173+
172174
const Comp = defineVaporComponent(() => {
173175
const n0 = template('<div></div>')()
174176
insert(
175-
createSlot('header', { title: () => 'header' }),
177+
createSlot('header', { title: () => src.value }),
176178
n0 as any as ParentNode,
177179
)
178180
return n0
@@ -191,6 +193,10 @@ describe('component: slots', () => {
191193
}).render()
192194

193195
expect(host.innerHTML).toBe('<div><h1>header</h1><!--slot--></div>')
196+
197+
src.value = 'footer'
198+
await nextTick()
199+
expect(host.innerHTML).toBe('<div><h1>footer</h1><!--slot--></div>')
194200
})
195201

196202
test('dynamic slot props', async () => {
@@ -263,17 +269,23 @@ describe('component: slots', () => {
263269
$: [
264270
() => ({
265271
name: 'header',
266-
fn: (props: any) => template(props.title)(),
272+
fn: (props: any) => {
273+
const el = template('<h1></h1>')()
274+
renderEffect(() => {
275+
setText(el, props.title)
276+
})
277+
return el
278+
},
267279
}),
268280
],
269281
})
270282
}).render()
271283

272-
expect(host.innerHTML).toBe('<div>header<!--slot--></div>')
284+
expect(host.innerHTML).toBe('<div><h1>header</h1><!--slot--></div>')
273285

274286
val.value = 'footer'
275287
await nextTick()
276-
expect(host.innerHTML).toBe('<div>footer<!--slot--></div>')
288+
expect(host.innerHTML).toBe('<div><h1>footer</h1><!--slot--></div>')
277289
})
278290

279291
test('dynamic slot outlet should be render correctly with slot props', async () => {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { unmountComponent } from '../src/component'
1515

1616
const define = makeRender()
1717

18-
describe.todo('createIf', () => {
18+
describe('createIf', () => {
1919
test('basic', async () => {
2020
// mock this template:
2121
// <div>
Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1-
import type { BlockFn, Fragment } from './block'
1+
import { type BlockFn, DynamicFragment } from './block'
2+
import { renderEffect } from './renderEffect'
23

34
export function createIf(
45
condition: () => any,
56
b1: BlockFn,
67
b2?: BlockFn,
78
once?: boolean,
89
// hydrationNode?: Node,
9-
): Fragment {
10-
return [] as any
10+
): DynamicFragment {
11+
const frag = __DEV__ ? new DynamicFragment('if') : new DynamicFragment()
12+
if (once) {
13+
frag.update(condition() ? b1 : b2)
14+
} else {
15+
renderEffect(() => frag.update(condition() ? b1 : b2))
16+
}
17+
return frag
1118
}

packages/runtime-vapor/src/block.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
unmountComponent,
77
} from './component'
88
import { createComment } from './dom/node'
9-
import { EffectScope } from '@vue/reactivity'
9+
import { EffectScope, pauseTracking, resetTracking } from '@vue/reactivity'
1010

1111
export type Block =
1212
| Node
@@ -29,7 +29,7 @@ export class Fragment {
2929
export class DynamicFragment extends Fragment {
3030
anchor: Node
3131
scope: EffectScope | undefined
32-
key: any
32+
current?: BlockFn
3333

3434
constructor(anchorLabel?: string) {
3535
super([])
@@ -40,10 +40,13 @@ export class DynamicFragment extends Fragment {
4040
document.createTextNode('')
4141
}
4242

43-
update(render?: BlockFn, key: any = render): void {
44-
if (key === this.key) return
45-
this.key = key
43+
update(render?: BlockFn): void {
44+
if (render === this.current) {
45+
return
46+
}
47+
this.current = render
4648

49+
pauseTracking()
4750
const parent = this.anchor.parentNode
4851

4952
// teardown previous branch
@@ -60,6 +63,7 @@ export class DynamicFragment extends Fragment {
6063
this.scope = undefined
6164
this.nodes = []
6265
}
66+
resetTracking()
6367
}
6468
}
6569

packages/runtime-vapor/src/componentSlots.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -109,26 +109,28 @@ export function createSlot(
109109
fallback?: Slot,
110110
): Block {
111111
const instance = currentInstance as VaporComponentInstance
112-
const fragment = new DynamicFragment('slot')
112+
const rawSlots = instance.rawSlots
113+
const isDynamicName = isFunction(name)
114+
const fragment = __DEV__ ? new DynamicFragment('slot') : new DynamicFragment()
113115
const slotProps = rawProps
114116
? new Proxy(rawProps, dynamicSlotsPropsProxyHandlers)
115117
: EMPTY_OBJ
116118

117-
// always create effect because a slot may contain dynamic root inside
118-
// which affects fallback
119-
renderEffect(() => {
120-
const slot = getSlot(instance.rawSlots, isFunction(name) ? name() : name)
119+
const renderSlot = (name: string) => {
120+
const slot = getSlot(rawSlots, name)
121121
if (slot) {
122-
fragment.update(
123-
() => slot(slotProps) || (fallback && fallback()),
124-
// TODO this key needs to account for possible fallback (v-if)
125-
// inside the slot
126-
slot,
127-
)
122+
fragment.update(() => slot(slotProps) || (fallback && fallback()))
128123
} else {
129124
fragment.update(fallback)
130125
}
131-
})
126+
}
127+
128+
// dynamic slot name or has dynamicSlots
129+
if (isDynamicName || rawSlots.$) {
130+
renderEffect(() => renderSlot(isFunction(name) ? name() : name))
131+
} else {
132+
renderSlot(name)
133+
}
132134

133135
return fragment
134136
}

0 commit comments

Comments
 (0)