Vue Directives
Vue's templating language allows you to interpolate the HTML code with JavaScript expressions and Vue directives. This templating pattern is often referred to as syntax sugar because it does not change how the code itself works, just how you use it. Syntax sugar allows you to clearly define template-specific logic inside of your HTML without the need to abstract this logic elsewhere in your project or return copious amounts of HTML directly from your JavaScript code. All Vue based directives are prefixed with v-*
, which indicates that it is a Vue specific attribute:
v-text
: Thev-text
directive has the same reactivity interpolation does, except you reference the same piece of data inside of a directive. Interpolation (curly braces){{ }}
is more performant than thev-text
directive; however, you may find yourself in situations where you have pre-rendered text from a server and want to override it once your Vue application has loaded. For example, you can predefine static placeholder text while the DOM waits for thedata
andv-text
attributes to eventually replace it.v-once
: As a directive, this is unique in that you pair it with other directives to augment how they function. Passing data viav-text
or interpolated curly braces into the HTML element this attribute is added to will stop the Vue instance from reloading the element with new data, removing the reactivity of the element. This is handy for situations where you want to render decorative elements using data, but do not want them to update when the data changes after the initial render.v-html
: This directive will render valid HTML in your data string inside of the HTML element it has been bound to. This directive is a heavier operation than the other directives, so limited usage is recommended when other options are not otherwise available.Note
<script>
tags can be run in this directive. Only render content originating from secure or trusted sources.v-bind
: This directive is one of the most widely used directives in Vue. Throughout Vue, you will be binding reactive data to HTML attributes and passing data into props using this directive's:attr
shortcut instead ofv-bind:attr
.v-if
: To control the display state of HTML elements inside the template, you will often usev-if
to completely remove elements from the DOM tree. So far, you have seen how to interpolate conditionals like this{{ isTrue ? 'Show this': 'Not this' }}
. With thev-if
directive, you can control entire blocks of HTML syntax.v-else-if
can be used likeelse if
statements and finish withv-else
, which is the equivalent to thecatch { ... }
declaration of anelse { ... }
statement in traditional JavaScript.v-show
: You can control the visible state of HTML elements by usingv-show
, which, instead of removing the element from the DOM tree, will apply adisplay: none
style. The difference between av-if
andv-show
is thatv-show
will remain as a block element in the DOM tree but will be hidden withcss
instead of being removed from the DOM tree. You also cannot chainv-show
withv-else
orv-else-if
.v-for
: Apply this to an element you want to repeat or iterate on. This directive requires an additional prop called:key
to allow it to properly reactively render; it can be as simple as a unique number.Consider an example where we iterate over the list element five times. Each list item will render its count (1, 2… 5):
<ul><!-- do not apply v-for to this <ul> element --> Â Â Â Â <li v-for="n in 5" :key="n">{{ n }}</li> </ul>
Now let's look at how some of the basic directives work.
Exercise 1.06: Basic Directives (v-text, v-once, v-html, v-bind, v-if, v-show)
More complicated components will use multiple directives to achieve the desired outcome. In this exercise, we will construct a component that uses several directives to bind, manipulate, and output data to a template view.
To access the code files for this exercise, refer to https://packt.live/3fdCNqa.
- Open a command-line terminal, navigate into the
Exercise1.06
folder, and run the following commands in order:> cd Exercise1.06/ > code . > yarn > yarn serve
Go to
https://localhost:8080
. - Compose the following syntax inside of
Exercise1-06.vue
. This uses the interpolation method that we have used in previous exercises and that will be very familiar by this point:<template>   <div>     <h1>{{ text }}</h1>   </div> </template> <script> export default {   data() {     return {       // v-text       text: 'Directive text',     }   }, } </script> <style lang="scss" scoped> h2 {   margin: 40px 0 0;   font-weight: normal; } </style>
- Replace the interpolation with the
v-text
attribute. You will notice the output will not change:<template>   <div>     <h1 v-text="text">Loading...</h1>   </div> </template> <script> export default {   data() {     return {       // v-text       text: 'Directive text',     }   }, } </script>
Figure 1.17 displays the output of the preceding code:
- Add the
v-once
directive on the same element. This will force this DOM element to only load thev-text
data once for as long as it exists in the page:<template>   <div>     <h1 v-once v-text="text">Loading...</h1>   </div> </template> <script> export default {   data() {     return {       // v-text       text: 'Directive text',     }   }, } </script> ...
- Underneath the
h1
element, include a newh2
element, which uses thev-html
attribute. Add a new data key calledhtml
, which contains a string with HTML formatting in it like the following:<template>   <div>     <h1 v-once v-text="text">Loading...</h1>     <h2 v-html="html" />   </div> </template> <script> export default {   data() {     return {       // v-text       text: 'Directive text',       // v-html       html: 'Stylise</br>HTML in<br/><b>your data</b>',     }   }, } </script> ...
Running the preceding code will generate an output as follows:
- Add a new
link
object to thedata
object that contains a bunch of information such as URL, target, title, and tab index. Inside the template, add a new anchor HTML element and bind thelink data
object to the HTML element using the colon syntax, for example,:href="link.url"
:<template>   <div>     <h1 v-once v-text="text">Loading...</h1>     <h2 v-html="html" />   </div> </template> <script> export default {   data() {     return {       // v-text       text: 'Directive text',       // v-html       html: 'Stylise</br>HTML in<br/><b>your data</b>',     }   }, } </script> ...
The following screenshot displays the output:
- Apply
v-if="false"
to theh1
element,v-else-if="false"
toh2
, andv-else
to thea
tag like this:<template>   <div>     <h1 v-if="false" v-once v-text="text">Loading...</h1>     <h2 v-else-if="false" v-html="html" />     <a       v-else       :href="link.url"       :target="link.target"       :tabindex="link.tabindex"       v-text="link.title"     />   </div> </template>
You should only see the
<a>
tag in the page since we have set the conditional statements tofalse
.The
v-else
condition will display as follows: - Change the template to use
v-show
instead of thev-if
statements:<template>   <div>     <h1 v-show="true" v-once v-text="text">Loading...</h1>     <h2 v-show="false" v-html="html" />     <a       :href="link.url"       :target="link.target"       :tabindex="link.tabindex"       v-text="link.title"     />   </div> </template>
The output of the preceding code will be as follows:
When you open the Elements
tab of your browser dev tools, you should be able to observe the h2
display state set to none
, as follows:
If v-show
results in a true
Boolean, it will leave the DOM element as is. If it resolves as false
, it will apply display: none
styling to the element.
In this exercise, we learned about the core Vue directives to control, bind, show, and hide HTML template elements without requiring any JavaScript outside of adding new data objects to your local state.
In the next section, we will learn how to achieve a two-way binding with the help of Vue's v-model
.