Skip to content

Commit

Permalink
feat(createReusableTemplate): inherit attrs (#3226)
Browse files Browse the repository at this point in the history
Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>
  • Loading branch information
wiidede and antfu committed Jul 30, 2023
1 parent c792da9 commit a32ae73
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 4 deletions.
16 changes: 16 additions & 0 deletions packages/core/createReusableTemplate/index.test.ts
Expand Up @@ -64,6 +64,22 @@ describe.skipIf(isVue2)('createReusableTemplate', () => {
expect(wrapper.text()).toBe('{"msg":"Foo"}{"msg":"Bar"}')
})

it('attrs', () => {
const [DefineFoo, ReuseFoo] = createReusableTemplate()

const wrapper = mount({
render() {
return h(Fragment, null, [
h(DefineFoo, () => h('div', { class: 'foo' })),
h(ReuseFoo, { id: 'bar', class: 'bar' }),
])
},
})

expect(wrapper.get('#bar')).toBeDefined()
expect(wrapper.get('#bar').classes()).toEqual(['foo', 'bar'])
})

it('slots', () => {
const [DefineFoo, ReuseFoo] = createReusableTemplate<{ msg: string }, { default: Slot }>()

Expand Down
25 changes: 21 additions & 4 deletions packages/core/createReusableTemplate/index.ts
Expand Up @@ -27,15 +27,27 @@ export type ReusableTemplatePair<
reuse: ReuseTemplateComponent<Bindings, Slots>
}

export interface CreateReusableTemplateOptions {
/**
* Inherit attrs from reuse component.
*
* @default true
*/
inheritAttrs?: boolean
}

/**
* This function creates `define` and `reuse` components in pair,
* It also allow to pass a generic to bind with type.
*
* @see https://vueuse.org/createReusableTemplate
*/
export function createReusableTemplate<
Bindings extends object, Slots extends Record<string, Slot | undefined> = Record<string, Slot | undefined>,
>(): ReusableTemplatePair<Bindings, Slots> {
Bindings extends object,
Slots extends Record<string, Slot | undefined> = Record<string, Slot | undefined>,
>(
options: CreateReusableTemplateOptions = {},
): ReusableTemplatePair<Bindings, Slots> {
// compatibility: Vue 2.7 or above
if (!isVue3 && !version.startsWith('2.7.')) {
if (process.env.NODE_ENV !== 'production')
Expand All @@ -44,6 +56,10 @@ export function createReusableTemplate<
return
}

const {
inheritAttrs = true,
} = options

const render = shallowRef<Slot | undefined>()

const define = defineComponent({
Expand All @@ -55,12 +71,13 @@ export function createReusableTemplate<
}) as DefineTemplateComponent<Bindings, Slots>

const reuse = defineComponent({
inheritAttrs: false,
inheritAttrs,
setup(_, { attrs, slots }) {
return () => {
if (!render.value && process.env.NODE_ENV !== 'production')
throw new Error('[VueUse] Failed to find the definition of reusable template')
return render.value?.({ ...keysToCamelKebabCase(attrs), $slots: slots })
const vnode = render.value?.({ ...keysToCamelKebabCase(attrs), $slots: slots })
return (inheritAttrs && vnode?.length === 1) ? vnode[0] : vnode
}
},
}) as ReuseTemplateComponent<Bindings, Slots>
Expand Down

0 comments on commit a32ae73

Please sign in to comment.