mirror of https://github.com/vuejs/core.git
feat(runtime-vapor): setup helpers useAttrs & useSlots (#172)
This commit is contained in:
parent
9f8bf4fc82
commit
db140a1e37
|
@ -0,0 +1,87 @@
|
||||||
|
import type { SetupContext } from '../src/component'
|
||||||
|
import {
|
||||||
|
createComponent,
|
||||||
|
defineComponent,
|
||||||
|
ref,
|
||||||
|
template,
|
||||||
|
useAttrs,
|
||||||
|
useSlots,
|
||||||
|
} from '../src'
|
||||||
|
import { makeRender } from './_utils'
|
||||||
|
|
||||||
|
const define = makeRender<any>()
|
||||||
|
|
||||||
|
describe('SFC <script setup> helpers', () => {
|
||||||
|
test.todo('should warn runtime usage', () => {})
|
||||||
|
|
||||||
|
test('useSlots / useAttrs (no args)', () => {
|
||||||
|
let slots: SetupContext['slots'] | undefined
|
||||||
|
let attrs: SetupContext['attrs'] | undefined
|
||||||
|
|
||||||
|
const Comp = {
|
||||||
|
setup() {
|
||||||
|
slots = useSlots()
|
||||||
|
attrs = useAttrs()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const count = ref(0)
|
||||||
|
const passedAttrs = { id: () => count.value }
|
||||||
|
const passedSlots = {
|
||||||
|
default: () => template('')(),
|
||||||
|
x: () => template('')(),
|
||||||
|
}
|
||||||
|
|
||||||
|
const { render } = define({
|
||||||
|
render: () => createComponent(Comp, passedAttrs, passedSlots),
|
||||||
|
})
|
||||||
|
render()
|
||||||
|
|
||||||
|
expect(typeof slots!.default).toBe('function')
|
||||||
|
expect(typeof slots!.x).toBe('function')
|
||||||
|
expect(attrs).toMatchObject({ id: 0 })
|
||||||
|
|
||||||
|
count.value++
|
||||||
|
expect(attrs).toMatchObject({ id: 1 })
|
||||||
|
})
|
||||||
|
|
||||||
|
test('useSlots / useAttrs (with args)', () => {
|
||||||
|
let slots: SetupContext['slots'] | undefined
|
||||||
|
let attrs: SetupContext['attrs'] | undefined
|
||||||
|
let ctx: SetupContext | undefined
|
||||||
|
const Comp = defineComponent({
|
||||||
|
setup(_, _ctx) {
|
||||||
|
slots = useSlots()
|
||||||
|
attrs = useAttrs()
|
||||||
|
ctx = _ctx
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const { render } = define({ render: () => createComponent(Comp) })
|
||||||
|
render()
|
||||||
|
expect(slots).toBe(ctx!.slots)
|
||||||
|
expect(attrs).toBe(ctx!.attrs)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe.todo('mergeDefaults', () => {
|
||||||
|
test.todo('object syntax', () => {})
|
||||||
|
test.todo('array syntax', () => {})
|
||||||
|
test.todo('merging with skipFactory', () => {})
|
||||||
|
test.todo('should warn missing', () => {})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('mergeModels', () => {
|
||||||
|
test.todo('array syntax', () => {})
|
||||||
|
test.todo('object syntax', () => {})
|
||||||
|
test.todo('overwrite', () => {})
|
||||||
|
})
|
||||||
|
|
||||||
|
test.todo('createPropsRestProxy', () => {})
|
||||||
|
|
||||||
|
describe.todo('withAsyncContext', () => {
|
||||||
|
test.todo('basic', async () => {})
|
||||||
|
test.todo('error handling', async () => {})
|
||||||
|
test.todo('should not leak instance on multiple awaits', async () => {})
|
||||||
|
test.todo('should not leak on multiple awaits + error', async () => {})
|
||||||
|
test.todo('race conditions', async () => {})
|
||||||
|
test.todo('should teardown in-scope effects', async () => {})
|
||||||
|
})
|
||||||
|
})
|
|
@ -0,0 +1,24 @@
|
||||||
|
import {
|
||||||
|
type SetupContext,
|
||||||
|
createSetupContext,
|
||||||
|
getCurrentInstance,
|
||||||
|
} from './component'
|
||||||
|
import { warn } from './warning'
|
||||||
|
|
||||||
|
// TODO: warning compiler-macros runtime usages
|
||||||
|
|
||||||
|
export function useSlots(): SetupContext['slots'] {
|
||||||
|
return getContext().slots
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useAttrs(): SetupContext['attrs'] {
|
||||||
|
return getContext().attrs
|
||||||
|
}
|
||||||
|
|
||||||
|
function getContext(): SetupContext {
|
||||||
|
const i = getCurrentInstance()!
|
||||||
|
if (__DEV__ && !i) {
|
||||||
|
warn(`useContext() called without active instance.`)
|
||||||
|
}
|
||||||
|
return i.setupContext || (i.setupContext = createSetupContext(i))
|
||||||
|
}
|
|
@ -110,6 +110,7 @@ export {
|
||||||
onErrorCaptured,
|
onErrorCaptured,
|
||||||
// onServerPrefetch,
|
// onServerPrefetch,
|
||||||
} from './apiLifecycle'
|
} from './apiLifecycle'
|
||||||
|
export { useAttrs, useSlots } from './apiSetupHelpers'
|
||||||
export {
|
export {
|
||||||
createVaporApp,
|
createVaporApp,
|
||||||
type App,
|
type App,
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {
|
import {
|
||||||
getCurrentInstance,
|
|
||||||
onBeforeMount,
|
onBeforeMount,
|
||||||
onBeforeUnmount,
|
onBeforeUnmount,
|
||||||
onMounted,
|
onMounted,
|
||||||
onUnmounted,
|
onUnmounted,
|
||||||
|
useAttrs,
|
||||||
watchEffect,
|
watchEffect,
|
||||||
} from 'vue/vapor'
|
} from 'vue/vapor'
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ const props = defineProps<{
|
||||||
baz: string
|
baz: string
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const attrs = getCurrentInstance()?.attrs
|
const attrs = useAttrs()
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
console.log({ ...attrs })
|
console.log({ ...attrs })
|
||||||
|
@ -29,8 +29,12 @@ onUnmounted(() => console.log('sub: unmounted'))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>sub-comp</div>
|
<h2>sub-comp</h2>
|
||||||
{{ props }}
|
<p>
|
||||||
{{ attrs }}
|
props: {{ props }}
|
||||||
{{ keys(attrs) }}
|
<br />
|
||||||
|
attrs: {{ attrs }}
|
||||||
|
<br />
|
||||||
|
keys(attrs): {{ keys(attrs) }}
|
||||||
|
</p>
|
||||||
</template>
|
</template>
|
||||||
|
|
Loading…
Reference in New Issue