From JSX to Vue: my favorite templating tips

briwa

briwa

Posted on June 15, 2019

From JSX to Vue: my favorite templating tips

Coming from using JSX, I am amazed by the built-in templating features that Vue has. Since I'm one of the late adopters, these might not be new to you, but I wish I had known these perks when I started migrating to Vue. So, hopefully this helps people who are in the midst of migrating, trying out Vue, or maybe thinking of using Vue?

Anyway, here are some of my favorites.

1. v-if, v-else and v-else-if for conditional rendering

In the component, there would always be some conditions for the templates to be rendered. I learned that v-if can toggle elements to be rendered while supplying the condition. An example would be:

<!-- Basket.vue -->
<section id="the-one-fruit-to-buy">
  <orange v-if="sourFruitSelected && isExpensive" />
  <grape v-if="sourFruitSelected && !isExpensive" />
  <apple v-if="!sourFruitSelected">
</section>

In this case, I only want to show one component at a time. If sourFruitSelected and isExpensive is true, orange would only be shown. Looking at the logic, this should look fine on browsers. But, if you look at the HTML, you would see something like this:

<!-- Inspecting the HTML -->
<section id="the-one-fruit-to-buy">
  <div id="orange-component"></div>
  <!----->
  <!----->
</section>

Two elements are rendered with <!-----> because the v-if statement is false. This is because every v-if is a single condition to the element it is targetting. Vue won't know that only one of the three elements is supposed to be shown if I'm using three v-ifs, which is three conditions to three different elements. Therefore, I should combine it with v-else-if and v-else:

<!-- Basket.vue -->
<section id="the-one-fruit-to-buy">
  <orange v-if="sourFruitSelected && isExpensive" />
  <grape v-else-if="sourFruitSelected && !isExpensive" />
  <apple v-else>
</section>

This means it is just one condition to toggle three elements. In the HTML, it would look like this:

<!-- Inspecting the HTML -->
<section id="the-one-fruit-to-buy">
  <div id="orange-component"></div>
</section>

But wait, there's more! While the conditional statement is valid, it can be hard to follow. How do we avoid sourFruitSelected and isExpensive logic repetitions? <template> tag can help you with that.

v-if is a directive, so it only works on a single element. If we put v-if to a <template> which is an empty wrapper of elements, we could improve the logic as follows:

<section class="the-one-fruit-to-buy">
  <template v-if="sourFruitSelected">
    <grape v-if="isExpensive">
    <orange v-else />
  <template>
  <apple v-else>
</section>

2. <component> tag to avoid repetitions on similar components

Supposedly I was building a chart component with Vue that looked like this:

<!-- Chart.vue -->
<chart
  :width="width"
  :height="height" />

Over time, I realized that I need more types of charts, built differently for each types, so the code now looks like this:

<!-- Chart.vue -->
<pie-chart
  v-if="type === 'pie'"
  :width="width"
  :height="height" />
<bar-chart
  v-else-if="type === 'bar'"
  :width="width"
  :height="height" />
<column-chart
  v-else-if="type === 'column'"
  :width="width"
  :height="height" />

You noticed that there is some kind of pattern, right? With <component> tag, I can improve the template as such:

<!-- Chart.vue -->
<component
  :is="`${type}-chart`" 
  :width="width"
  :height="height" />

This basically means it will render a component that has ${type}-chart as its name, defined under :is. Since all components share the same props (width and height), both will be passed down to each rendered components.

Do note that all the possible components have to be registered in the parent (or installed globally) in order for this to work.

3. <slot> tag for shared component reusability

Say I was implementing a modal component, and I would use it as such:

<!-- Parent.vue -->
<modal :text="'Lorem ipsum'" />

The actual component would just be:

<!-- Modal.vue -->
<div class="modal">
  {{ text }}
</div>

Then, I wanted to add actual HTML elements to the modal, like forms. Not just a simple text. How do I parse the string prop as HTML?

With <slot>, you can place any content from the parent down to the component's template. You shouldn't be using the prop anyway. So, the modal component template would be:

<!-- Modal.vue -->
<div class="modal">
  <slot />
</div>

And the parent component that uses the modal would just be:

<!-- Parent.vue -->
<modal>
  <form>
    <h3>Do you want to delete these files permanently?</h3>
    <button>Cancel</button>
    <button>Delete</button>
  </form>
</modal>

I think slots is one of the most interesting feature in Vue, taking component reusability to a whole new level. Be sure to check the docs for more in-depth details.

4. .camel prop modifier for specific camel-case HTML attributes

There are times when the HTML requires certain attributes to be written in camel case. Consider this example:

<!-- Svg.vue -->
<svg :view-box="viewBox">
  <circle cx="0" cy="0" r="50"/>
</svg>

viewBox was written in kebab-case because it is recommended for props by the styleguide. I thought Vue would know and convert it back to camel case anyway.

Well, it won't! It will be rendered as-is. You have to specifically tell Vue that the attribute needs to be in camel case when rendered. You can fix that with .camel:

<!-- Svg.vue -->
<svg :view-box.camel="viewBox">
  <circle cx="0" cy="0" r="50"/>
</svg>

The viewBox will be rendered properly in the HTML.

5. v-once directive for cheap, static content in templates

Static contents that won't ever change can be optimized by adding v-once on the root of the content, so that it is only rendered once regardless. The docs says it all.

I think this is one of the least mentioned features in Vue, because I don't think static content has ever come as major performance bottlenecks among Vue users. But, if you're interested, you can use them and let me know how it goes. Or, if maybe anyone has gained any significant performance improvements with v-once, let me know as well, I would love to learn.

Notable mentions

I'd like to also mention v-model which is a data communication model in-between parent and child, and <transition> which is a built-in component for transitioning between elements, but I think each deserves its own article due to their robustnesses and the details to cover. Stay tuned!


Of course, I'm not saying JSX can't do what Vue does. I think with JSX, anything is possible, since it's just Javascript. The point of the article is more towards the ease of using Vue's built-ins to achieve what JSX can do (or better?). JSX has its own beauty, especially the type-checking, that I must say. In other news, you can still use JSX with Vue!

By the way, if you have your own favorite Vue tips that aren't covered here, or if you have any feedback on the tips, do share it below in the comments. Also, these tips are already covered in their official docs, just thought I'd share with my own use cases.

Thank you for reading!


Cover image by Jeffrey Hamilton on Unsplash.

💖 💪 🙅 🚩
briwa
briwa

Posted on June 15, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related