Subscribe on changes!
avatar
Oct 12th 2022

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 写,但是 tsxslotexpose 是无法实现代码提示的。 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),
    ]))
  }
avatar
Oct 15th 2022

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>