Skip to content

Commit db140a1

Browse files
authored
feat(runtime-vapor): setup helpers useAttrs & useSlots (#172)
1 parent 9f8bf4f commit db140a1

File tree

4 files changed

+122
-6
lines changed

4 files changed

+122
-6
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import type { SetupContext } from '../src/component'
2+
import {
3+
createComponent,
4+
defineComponent,
5+
ref,
6+
template,
7+
useAttrs,
8+
useSlots,
9+
} from '../src'
10+
import { makeRender } from './_utils'
11+
12+
const define = makeRender<any>()
13+
14+
describe('SFC <script setup> helpers', () => {
15+
test.todo('should warn runtime usage', () => {})
16+
17+
test('useSlots / useAttrs (no args)', () => {
18+
let slots: SetupContext['slots'] | undefined
19+
let attrs: SetupContext['attrs'] | undefined
20+
21+
const Comp = {
22+
setup() {
23+
slots = useSlots()
24+
attrs = useAttrs()
25+
},
26+
}
27+
const count = ref(0)
28+
const passedAttrs = { id: () => count.value }
29+
const passedSlots = {
30+
default: () => template('')(),
31+
x: () => template('')(),
32+
}
33+
34+
const { render } = define({
35+
render: () => createComponent(Comp, passedAttrs, passedSlots),
36+
})
37+
render()
38+
39+
expect(typeof slots!.default).toBe('function')
40+
expect(typeof slots!.x).toBe('function')
41+
expect(attrs).toMatchObject({ id: 0 })
42+
43+
count.value++
44+
expect(attrs).toMatchObject({ id: 1 })
45+
})
46+
47+
test('useSlots / useAttrs (with args)', () => {
48+
let slots: SetupContext['slots'] | undefined
49+
let attrs: SetupContext['attrs'] | undefined
50+
let ctx: SetupContext | undefined
51+
const Comp = defineComponent({
52+
setup(_, _ctx) {
53+
slots = useSlots()
54+
attrs = useAttrs()
55+
ctx = _ctx
56+
},
57+
})
58+
const { render } = define({ render: () => createComponent(Comp) })
59+
render()
60+
expect(slots).toBe(ctx!.slots)
61+
expect(attrs).toBe(ctx!.attrs)
62+
})
63+
64+
describe.todo('mergeDefaults', () => {
65+
test.todo('object syntax', () => {})
66+
test.todo('array syntax', () => {})
67+
test.todo('merging with skipFactory', () => {})
68+
test.todo('should warn missing', () => {})
69+
})
70+
71+
describe('mergeModels', () => {
72+
test.todo('array syntax', () => {})
73+
test.todo('object syntax', () => {})
74+
test.todo('overwrite', () => {})
75+
})
76+
77+
test.todo('createPropsRestProxy', () => {})
78+
79+
describe.todo('withAsyncContext', () => {
80+
test.todo('basic', async () => {})
81+
test.todo('error handling', async () => {})
82+
test.todo('should not leak instance on multiple awaits', async () => {})
83+
test.todo('should not leak on multiple awaits + error', async () => {})
84+
test.todo('race conditions', async () => {})
85+
test.todo('should teardown in-scope effects', async () => {})
86+
})
87+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import {
2+
type SetupContext,
3+
createSetupContext,
4+
getCurrentInstance,
5+
} from './component'
6+
import { warn } from './warning'
7+
8+
// TODO: warning compiler-macros runtime usages
9+
10+
export function useSlots(): SetupContext['slots'] {
11+
return getContext().slots
12+
}
13+
14+
export function useAttrs(): SetupContext['attrs'] {
15+
return getContext().attrs
16+
}
17+
18+
function getContext(): SetupContext {
19+
const i = getCurrentInstance()!
20+
if (__DEV__ && !i) {
21+
warn(`useContext() called without active instance.`)
22+
}
23+
return i.setupContext || (i.setupContext = createSetupContext(i))
24+
}

packages/runtime-vapor/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ export {
110110
onErrorCaptured,
111111
// onServerPrefetch,
112112
} from './apiLifecycle'
113+
export { useAttrs, useSlots } from './apiSetupHelpers'
113114
export {
114115
createVaporApp,
115116
type App,

playground/src/sub-comp.vue

+10-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<script setup lang="ts">
22
import {
3-
getCurrentInstance,
43
onBeforeMount,
54
onBeforeUnmount,
65
onMounted,
76
onUnmounted,
7+
useAttrs,
88
watchEffect,
99
} from 'vue/vapor'
1010
@@ -14,7 +14,7 @@ const props = defineProps<{
1414
baz: string
1515
}>()
1616
17-
const attrs = getCurrentInstance()?.attrs
17+
const attrs = useAttrs()
1818
1919
watchEffect(() => {
2020
console.log({ ...attrs })
@@ -29,8 +29,12 @@ onUnmounted(() => console.log('sub: unmounted'))
2929
</script>
3030

3131
<template>
32-
<div>sub-comp</div>
33-
{{ props }}
34-
{{ attrs }}
35-
{{ keys(attrs) }}
32+
<h2>sub-comp</h2>
33+
<p>
34+
props: {{ props }}
35+
<br />
36+
attrs: {{ attrs }}
37+
<br />
38+
keys(attrs): {{ keys(attrs) }}
39+
</p>
3640
</template>

0 commit comments

Comments
 (0)