Discussion on Reusing Templates
What problem does this feature solve?
- I don't want to use jsx
For example:
<script lang="ts" setup>
defineProps<{
title: string
unit: string
unitIsRight: boolean
}>()
</script>
<!-- reuse div.unit -->
<template>
<div>
<div v-if="!unitIsRight" class="unit">
<slot name="unit">
{{ unit }}
</slot>
</div>
<div>{{ title }}</div>
<div v-if="unitIsRight" class="unit">
<slot name="unit">
{{ unit }}
</slot>
</div>
</div>
</template>
写组件的时候经常会有这个问题,然后又换成 tsx
写,但是 tsx
的 slot
和 expose
是无法实现代码提示的。
You often get this problem when you write components, and then switch to tsx
, but slot
and expose
don't allow for code hints.
What does the proposed API look like?
<script lang="ts" setup>
defineProps<{
title: string
unit: string
unitIsRight: boolean
}>()
</script>
<template name="unit">
<div v-if="!unitIsRight" class="unit">
<slot name="unit">
{{ unit }}
</slot>
</div>
</template>
<template>
<div>
<template v-if="!unitIsRight" is="unit"></template>
<div>{{ title }}</div>
<template v-if="unitIsRight" is="unit"></template>
</div>
</template>
Template to:
return (_ctx, _cache) => {
const __template = {
unit: () => (_openBlock(), _createElementBlock('div', { class: 'unit' }, [
_renderSlot(_ctx.$slots, 'unit', {}, () => [
_createTextVNode(_toDisplayString(props.unit), 1 /* TEXT */),
]),
])),
}
return (_openBlock(), _createElementBlock('div', null, [
(!props.unitIsRight)
? __template.unit()
: _createCommentVNode('v-if', true),
_createElementVNode('div', null, _toDisplayString(props.title), 1 /* TEXT */),
(props.unitIsRight)
? __template.unit()
: _createCommentVNode('v-if', true),
]))
}
Interesting! I always go for creating a child component when I see repetition and while reading the problem I intuitively thought of solving it that way.
But having multiple templates in order to reuse them inside a SFC looks amazing. I am thinking that this way of doing it, wouldn't require a new instance to be created right? Because if a new instance is created, then I guess there is no need to do that, we could just create a child component.
So in terms of optimizations, having this way of reusing templates, would probably result in fewer component instances in userland.
Thinking of logical concerns, this can align well I believe. Think for example:
<script setup>
const count = ref(0)
function increase() {
count.value++
}
const user = ref({ name: 'Roland' })
function clear() {
user.value = { name: '' }
}
</script>
<template name="count">
Count is: {{ count }}
<button @click="increase">Increase</button>
</template>
<template name="user">
User name is: {{ user.name }}
<button @click="clear">Clear</button>
</template>
<template>
<div>
<template is="count"></template>
<hr />
<template is="user"></template>
</div>
</template>