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>