Vue.js Directives
Let’s start:
v-text
Fairly simple directive, which sets the textContent property for an element:
<div>
<p v-text="text"></p>
</div>
<!-- same as -->
<p> {{text}} </p>To be honest for the most case I would prefer the latter way and using it is more convenient for me.
v-html
Basically setting the inner HTML value of an element:
<div v-html="html"></div>Warning: When using this directive do not use a user-provided content, that will leave you vulnerable to XSS attacks use it only if you trust the content provided
Use it with caution!
Scoped css does not apply inside the v-html
v-show
Changes the CSS display property based on true/false value by adding inline CSS style to the element it also tries to take into consideration the initial value of the property. Triggers transition when showing the element
<div>
<p v-show="isVisible"> Text to show/hide </p>
</div>Since it’s using the the display property the element is present on the page but not rendered, which is not what one always wants, because it can cause some problems with the layout, I had a few cases in which a hidden element messes the other elements on the page, because of the CSS styles used.
v-if
Renders an element, template or fragment on a given condition, when the expression provided is false the inner content is not rendered at all.
<div>
<p v-if="isVisible"> Text to show/hide </p>
</div>Very often used with template to show/hide a content from the page, to be honest I’ve preferred to use it, instead of v-show it’s because with it, the element won’t be present on the page at all and it won’t mess up anything else. I find myself reaching for it very often in combination with v-for more about it further below.
v-else
There is no if without the else, I’m right? This directive is everything you expect from always used in combination with the v-if directive and “completes it”.
<div>
<p v-show="isVisible"> Now you see me </p>
<p v-else> Now you don't </p>
</div>it doesn’t expects any expression the only thing is that, the previous element needs to have v-if on it this is the only requirement for it.
For me I’m using it a lot with the template directive, for things like Active and Deactivated status or some other pair of values that you are that comes in pairs.
v-else-if
Again used in combination with the v-if it expects an expression it can be chained:
<div>
<p v-if="status == 'Active'"> You are active</p>
<p v-else-if="status == 'Deactivated'"> You are not active </p>
<p v-else-if="status == 'Deleted'"> You are deleted</p>
<p v-else> Your status is {{ status }}</p>
</div>Always comes after an v-if directive and at some point it should be followed with v-else
v-for
Render element or template multiple times based on data set.
After v-if this is the directive that I’m using the most in my day-to-day work flow, something keen that should mentioned here:
v-if has a higher priority than v-for and they cannot be used on the same element:
Don’t use them like that:
<template v-if="isActive" v-for="item in items">
<span>{{ item.name }}</span>
</template>from my experience almost every major IDE will show warning if try to use together.
Use it like this:
<template v-if="isActive">
<template v-for="item in items">
<span>{{ item.name }}</span>
</template>
</template>on a separate elements, first the check then the rendering of the data set. Those three goes so well with each other.
v-on
Along with v-if and v-for this is one of the most used directives at least for me, regarding of what components or layout there is you will definitely need to attach them to elements:
<div>
<button v-on:click="show">Click me</button>
</div>Me personally I prefer the shorthand more:
<div>
<button @click="show">Click me</button>
</div>it also can be used with anonymous functions:
<div>
<button @click="() => { console.log('Clicked') }">Click me</button>
</div>it’s more intuitive for me and easier to remember when used in every day workflow.
Along with the v-on there some additional modifiers that can be used:
.stop- callevent.stopPropagation()..prevent- callevent.preventDefault()..capture- add event listener in capture mode..self- only trigger handler if event was dispatched from this element..{keyAlias}- only trigger handler on certain keys..once- trigger handler at most once..left- only trigger handler for left button mouse events..right- only trigger handler for right button mouse events..middle- only trigger handler for middle button mouse events..passive- attaches a DOM event with{ passive: true }.
one of the the reasons I love VueJS is that it provides everything you need in a comprehensive way, without any over the top syntax or tons of information that you need to review before using them.
<!-- shorthand dynamic event -->
<button @[event]="doThis"></button>
<!-- stop propagation -->
<button @click.stop="doThis"></button>
<!-- prevent default -->
<button @click.prevent="doThis"></button>
<!-- prevent default without expression -->
<form @submit.prevent></form>
<!-- chain modifiers -->
<button @click.stop.prevent="doThis"></button>
<!-- key modifier using keyAlias -->
<input @keyup.enter="onEnter" />
<!-- the click event will be triggered at most once -->
<button v-on:click.once="doThis"></button>
<!-- object syntax -->
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>just like that adding a dot and the modifier name after the event name: as simple as you like.
The .prop modifier also has a dedicated shorthand, .:
<div :someProperty.prop="someObject"></div>
<!-- equivalent to -->
<div .someProperty="someObject"></div>The .camel modifier allows camelizing a v-bind attribute name when using in-DOM templates, e.g. the SVG viewBox attribute:
<svg :view-box.camel="viewBox"></svg>.camel is not needed if you are using string templates, or pre-compiling the template with a build step.
v-model
One of my absolute favorite directives in VueJs and probably the one I’m using the most, it allows you two-away binding on a input element or a component.
It comes with a few additional modifiers:
.lazy- listen tochangeevents instead ofinput.number- cast valid input string to numbers.trim- trim input
But it worth mentioning that it can be used on a limited number of elements:
<input><select><textarea>components
very useful, if you are using VueJS in your workflow I bet you are using it a lot.
v-slot
Indicate slots, whether named or scoped, that anticipate receiving props.
Expect passed JS expression to be valid, and gives you the ability to used named slots:
<!-- Named slots -->
<BaseLayout>
<template v-slot:header>
Header content
</template>
<template v-slot:default>
Default slot content
</template>
<template v-slot:footer>
Footer content
</template>
</BaseLayout>
<!-- Named slot that receives props -->
<InfiniteScroll>
<template v-slot:item="slotProps">
<div class="item">
{{ slotProps.item.text }}
</div>
</template>
</InfiniteScroll>
<!-- Default slot that receive props, with destructuring -->
<Mouse v-slot="{ x, y }">
Mouse position: {{ x }}, {{ y }}
</Mouse>Limited to:
<template>components (for a lone default slot with props)
v-pre
Skip compilation for this element and all its children.
Does not expect expression
Inside the element with v-pre, all Vue template syntax will be preserved and rendered as-is. The most common use case of this is displaying raw mustache tags.
<span v-pre>{{ this will not be compiled }}</span>v-once
Not so popular directives, which doesn’t in case means they are not as useful as the others.
v-once can be used to optimize update perfoemance of your components and pages.
Render the element and component once only, and skip future updates.On subsequent re-renders, the element/component and all its children will be treated as static content and skipped. This can be used to optimize update performance:
<!-- single element -->
<span v-once>This will never change: {{msg}}</span>
<!-- the element have children -->
<div v-once>
<h1>comment</h1>
<p>{{msg}}</p>
</div>
<!-- component -->
<MyComponent v-once :comment="msg"></MyComponent>
<!-- `v-for` directive -->
<ul>
<li v-for="i in list" v-once>{{i}}</li>
</ul>and it getting better since VueJS 3.2 you can memoize part of the template with invalidation conditions using v-memo (which we will take a look at bit further down)
v-memo(3.2+)
Cache a section of the template. Applicable to both elements and components, this directive requires an array of fixed length, representing dependency values for caching comparison. If all values in the array match those from the last render, updates for the entire sub-tree will be omitted.
<div v-memo="[valueA, valueB]">
...
</div>If, upon component re-rendering, both valueA and valueB remain unchanged, updates for this <div> and its children will be skipped. Additionally, the creation of the Virtual DOM VNode will be bypassed, as the cached copy of the sub-tree can be reused.
It is important to specify the cache array correctly, otherwise we may skip updates that should indeed be applied. v-memo with an empty dependency array (v-memo="[]") would be functionally equivalent to v-once.
Usage with v-for :
The v-memo directive is designed for micro-optimizations in performance-critical situations and is generally needed infrequently. It can be particularly beneficial in scenarios such as rendering extensive v-for lists, especially when the length exceeds 1000.
<div v-for="item in list" :key="item.id" v-memo="[item.id === selected]">
<p>ID: {{ item.id }} - selected: {{ item.id === selected }}</p>
<p>...more child nodes</p>
</div>A litle warning here if you want to use v-memo with v-for :
When using
v-memowithv-for, make sure they are used on the same element.v-memodoes not work insidev-for.
v-cloak
Used to hide un-compiled template until they are properly rendered, it can prevents showing component which was not yet rendered and some raw elements to be shown to the user.
This directive is only needed in no-build-step setups.
When using in-DOM templates, there can be a “flash of un-compiled templates”: the user may see raw mustache tags until the mounted component replaces them with rendered content.
v-cloak will remain on the element until the associated component instance is mounted. Combined with CSS rules such as [v-cloak] { display: none }, it can be used to hide the raw templates until the component is ready.
[v-cloak] {
display: none;
}<div v-cloak>
{{ message }}
</div>The <div> will not be visible until the compilation is done.
Conclusion
A bit longer read than usual, but with a lot of new ideas and tools that can help you with some specific problem that you have for ages.
VueJS never seize to amaze with new thing to use to make the development process while using it, even better than it is now. Go through the list and pick your poison.
Share this post