For React developers, transitioning to Vue.js can be challenging due to the considerable differences between the frameworks. While Vue’s reactivity model might be a thing that many come to love once they learn how it works (and even want to bring the benefits of this approach to React world with solutions like Preact Signals) the same can’t be said about Vue’s template syntax.
Coming from a React background and being accustomed to leveraging the full power of JSX it’s hard to let go of ability to use temporary variables and being able to assemble markup directly within the control flow of your JavaScript code when switching to Vue and trying to get used to writing templates which feels less flexible and more restrictive.
Good news is it doesn’t have to be this way anymore cause recently there finally appeared a cure for this pain that had been unaddressed for a long time with VueUse createReusableTemplate. Let’s see how it can make writing your templates less cumbersome.
One of the most common bummers with templates comes from inability to define a template part and reuse it across template, for example when some block needs to appear in different places in the markup depending on some condition.
It doesn’t always make sense to extract a part into a separate component of it’s own. Even with a separate component it’s quite common that they need to be passed numerous props and simply duplicating props declaration multiple times is too much of a repetition that grows your template and leaves you open to potential to introduce a bug: when a new prop needs to be added to all of the occurrences it’s easy to overlook one (and then debug it for half hour 🥲).
Let’s consider a case where you need to render some template block in header or footer depending on whether view is compact. This is not a problem in React where you can easily do something like this:
// Component.tsx
const block = (
<div
class="block"
onClick="handleClick"
{/* here may go other prop definitions, perhaps complex ones */}
>
Block that should be reused
</div>
);
return (
<div class="container">
<div class="header">
Header content
{!isCompact && block}
</div>
<div class="footer">
Footer content
{isCompact && block}
</div>
</div>
);
With Vue by default you have no other option but to duplicate block:
// Component.vue
<template>
<div class="container">
<div class="header">
Header content
<div
v-if="!isCompact"
class="block"
@click="handleClick"
>
Block that should be reused
</div>
</div>
<div class="footer">
Footer content
<div
v-if="isCompact"
class="block"
@click="handleClick"
>
Block that should be reused
</div>
</div>
</div>
</template>
VueUse is a utility library aimed at solving common use-cases packed with useful composables and other helpers similar to react-use in the React ecosystem.
**VueUse** provides **createReusableTemplate** function that can help to DRY your templates.
As it’s a separate package and not a part of Vue framework API it needs to be installed with a command like:
npm i @vueuse/core
Check out the installation guide for instructions for your package manager of choice or meta framework (if you’re using Nuxt).
To reuse markup you need to first call createReusableTemplate()
in <script>
section:
// Component.vue
<script setup lang="ts">
import { createReusableTemplate } from '@vueuse/core'
const [DefineTemplate, ReuseTemplate] = createReusableTemplate()
</script>
It returns two component constructors: DefineTemplate
to wrap the template part you want to reuse and ReuseTemplate
to render the part in place. You can then use them in <template>
like so: