Making the front-end dynamic in web development involves logic that reorganizes or rewrites various nodes of the HTML DOM tree. In simple terms, the HTML in our pages needs to be updated or changed without triggering page reloads.
In Vue.js, this is made possible by directly binding the target HTML tag's inner content, attributes, and events to the Vue.js instance with the help of its custom directives.
These Vue.js directives help us apply JavaScript operations directly on the template HTML while Vue.js handles the nitty-gritty work we'd normally do in vanilla JavaScript under the hood, simplifying the whole development process for us.
Custom Vue.js Directives
Vue.js has a number of these custom directives that assist us in making the HTML markup in our templates dynamic. Let's get acquainted to some of them through simple demonstrations.
Take a look at the following example.
<html>
<style>
.box {
background-color: coral;
width: 100px;
height: 100px;
margin: 20px;
}
</style>
<div id="app">
<div class="box" v-show="showBox"></div>
</div>
<script src="https://unpkg.com/vue@3"></script>
<script>
let app = Vue.createApp({
data() {
return {
showBox: true,
};
},
mounted() {
const toggleVisibility = () => {
this.showBox = !this.showBox;
};
let intervalId = setInterval(toggleVisibility, 1000);
const stopToggle = () => {
this.showBox = true;
clearInterval(intervalId);
};
let timeoutId = setTimeout(stopToggle, 20000);
},
}).mount('#app');
</script>
</html>
When you open the above example on your browser, you'll see a color box appearing and disappearing for a span of 20 seconds.
The v-show directive
We achieve this blinking effect by toggling the state of the showBox variable between the true and false states. We can find this in the logic defined in the mounted hook. And to bind that state to our box (the div block with the .box
class) we use the v-show Vue.js directive on it.
The v-show is a custom Vue.js directive that modifies the display
style of a HTML element based on the truthiness of the variable passed to it. If it's an expression or value that is falsy, it adds a display: none
style to the HTML element in question.
v-show is among Vue.js' conditional directives, i.e. directives that fulfill a task based on the truthiness of the value being observed. Other conditional Vue.js directives include v-if, v-else-if, and v-else. We will look at these in more depth later.
The v-bind directive
Let's take a look at another example.
<html>
<style>
meter {
height: 3em;
width: 15em;
}
</style>
<div id="app">
<h1>Vue City Water Flow Rate Levels</h1>
<h2>({{'{{'}} level.toFixed() {{'}}'}} m³/hour)</h2>
<meter
min="0"
max="100"
low="33"
high="66"
optimum="80"
v-bind:value="level"
></meter>
<br />
</div>
<script src="https://unpkg.com/vue@3"></script>
<script>
let app = Vue.createApp({
data() {
return {
level: 0,
};
},
mounted() {
const fluctuateLevel = () => {
this.level = Math.random() * 15 + 60;
};
let intervalId = setInterval(fluctuateLevel, 200);
},
}).mount('#app');
</script>
</html>
In the above example, we are observing the fluctuating water flow rate in our imaginary city - "Vue City".
As evident, we are simulating the water levels between values 60 and 75 inside the fluctuateLevel() function inside the mounted hook.
To succeed in our demonstration, we need to make sure that the value attribute of the meter element keeps changing by being updated by the value of the level Vue.js variable. We achieve this by attaching the v-bind directive whose function is to bind the values of reactive Vue.js variables to HTML element attributes, in our case the level variable to the value attribute of the meter element (v-bind:value="level"
). Hence, whenever level changes, the element's attribute immediately gets the updated value, in-turn updating the meter we see on the page.
Binding HTML with the v-html directive
Not only does Vue.js support binding for plain variables, but it also has a custom directive that handles the binding for HTML markup, the v-html.
This directive can be quite handy when trying to display content such as a blog's article content fetched from an external data API.
Let's demonstrate this in an example.
<html>
<div id="app">
<h1>{{'{{'}} title {{'}}'}}</h1>
<div>
<h2>With v-html</h2>
<article v-html="htmlContent"></article>
</div>
<div>
<h2>without v-html</h2>
<article> {{'{{'}} htmlContent {{'}}'}} </article>
</div>
</div>
<script src="https://unpkg.com/vue@3"></script>
<script>
let app = Vue.createApp({
data() {
return {
title: '',
htmlContent: ''
}
},
async mounted() {
await fetch('https://hacker-news.firebaseio.com/v0/item/121003.json?print=pretty')
.then((res) => res.json())
.then((res) => {
console.log(res);
this.htmlContent = res.text;
this.title = res.title;
})
},
}).mount("#app");
</script>
</html>
In the example above, we are fetching data from the Hacker news API and extracting a title and text containing HTML tags.
Trying to render the HTML content inside the htmlContent variable inside the mustache syntax as seen in the first section does not give us intended results as the HTML content is plotted as is. This is not what we want to see in such a case.
Binding the same variable onto the second article tag using the v-html directive gives us what we want, having the HTML inside our variable rendered as part of the existing page template.
The asynchronous fetch method above is nothing other than a helper that is assisting us in fetching remote data. You can read more about the fetch API here.
We will cover more tutorials involving fetching data from external data API in the future. This is just a simple example demonstrating the gist of it.
After getting introduced to Vue.js directives, we'll be going in depth on conditional and list rendering inside Vue.js templates while using them in the next post.
Top comments (0)