Table of contents
Just as any other JavaScript framework, Vue.js needs to work with data for it to be rendered useful. On this post, we are going to explore working with data inside Vue.js.
The Data Property
In Vue.js, data declaration is done inside the data property, it is a function that returns an object containing all the variables we can use on the template and inside other parts of the Vue.js app.
Let's create a new Vue.js app to demonstrate this.
<div id="app">
<p>{{ firstName }} {{ lastName }}</p>
</div>
<script src="https://unpkg.com/vue@3"></script>
<script>
let app = Vue.createApp({
data: function () {
return {
firstName: 'vue',
lastName: 'noob',
};
},
}).mount('#app');
</script>
To display data inside our template as seen from the above example, we add the data property in the first argument of the createApp() function. We return an object containing our data variables, as we have done with firstName and lastName above. The data returned is reactive, meaning, any changes made to our variables will be reflected throughout the app instance. More on data reactivity in Vue.js will be covered in later posts.
We can simplify the data method from the above example as follows.
data() {
return {
firstName: 'vue',
lastName: 'noob',
};
},
As we've seen in our example, firstName and lastName being top level properties returned by the data method will be accessed as independent variables inside our app. They will be accessible directly inside the template's mustache syntax, and, in all other parts of the Vue app starting from the created hook and downwards on the Vue.js app lifecycle including methods inside this. We'll explore Vue.js lifecycle hooks in a later post.
Beginning with the template, let's see how the variables can be displayed inside the mustache delimiters.
<div id="app">
<p>{{ firstName }} {{ lastName }}</p>
+ <p>{{ firstName }} is of type {{ typeof firstName }}</p>
+ <p>{{ `${firstName} ${lastName}` }}</p>
+ <p>{{ firstName + ' ' + lastName }}</p>
+ <p>{{ firstName.toLowercase() + ' ' + lastName.toUppercase() }}</p>
+ <p>{{ (firstName + ' ' + lastName).split(" ").map(x => x.charAt(0).toUpperCase() + x.slice(1)) }}</p>
+ <p>{{ (firstName + ' ' + lastName).length < 12 ? "That's a short name" : "That's a long name" }}</p>
</div>
In the above template, all paragraphs give the expected results just as expected in any other JavaScript environment. As explained in the previous post the expressions inside the mustache are subject to all JavaScript operations applicable to their specific data types, and we can see this in practice in this example.
Note that, all manipulations done to variables inside the mustache delimiters are solely for presentational purposes, the data values are never changed in this way. This is what we call one-way data binding, i.e data flows in one direction, in our case, from the data property to the template.
Vue.js does have support for two way binding, a subject that will be covered later.
If you have noticed, it takes a moment to figure out what some expressions within the above template are supposed to do, they are bloated and in being so become hard to maintain, especially if our app grows in features.
We can fix this with the aid of Vue.js computed properties.
The Computed Properties
Vue.js computed properties help simplify complex logic involving reactive data, enhancing its readability hence maintainability. The computed properties live inside the computed property of the Vue instance. Let's see how this can help fix the situation that we've seen in our example above.
Instead of placing this cluttered code.
<p>
{{ (firstName + ' ' + lastName).split(" ").map(x => x.charAt(0).toUpperCase() + x.slice(1)) }}
</p>
We can create a computed property for that logic as follows.
let app = Vue.createApp({
data() {
return {
firstName: 'vue',
lastName: 'noob',
};
},
+ computed: {
+ capitalizeName() {
+ return (this.firstName + ' ' + this.lastName).split(" ").map(x => x.charAt(0).toUpperCase() + x.slice(1));
+ }
}
}).mount('#app');
Afterwards, we can replace the cluttered template expression with a readable variable as follows.
<p>
{{ capitalizeName }}
</p>
From here on, whenever we need to have the name capitalized, we'll just use the computed property placing it just as we would any data variable within our template code, no need to repeat the long expressions when we need the same complex logic applied on our data inside our templates.
The same can be done for the rest of the bloated expressions inside the template code.
let app = Vue.createApp({
data() {
return {
firstName: 'vue',
lastName: 'noob',
};
},
computed: {
capitalizeName() {
return (this.firstName + ' ' + this.lastName).split(" ").map(x => x.charAt(0).toUpperCase() + x.slice(1));
},
+ fullName() {
+ return this.firstName + " " + this.lastName;
+ },
+ firstNameAndType() {
+ return this.firstName + " is of type " + typeof this.firstName;
+ },
+ selectiveCapitalization() {
+ return this.firstName.toLowercase() + ' ' + this.lastName.toUppercase();
+ },
+ nameLengthComment() {
+ return (firstName + ' ' + lastName).length < 12 ? "That's a short name" : "That's a long name";
+ }
},
}).mount('#app');
Then, we'll replace the cluttered code in our template with the cleaner computed properties.
<p>{{ fullName }}</p>
<p>{{ firstNameAndType }}</p>
<p>{{ fullName }}</p>
<p>{{ fullName }}</p>
<p>{{ selectiveCapitalization }}</p>
<p>{{ capitalizeName }}</p>
<p>{{ nameLengthComment }}</p>
On this post, we have covered how to work with data in Vue.js by declaring and using variables. We also got introduced to Vue.js computed properties, and saw how they can be used to complement variables or replace them when their expressions become complex within our templates, helping make our code readable and maintainable in the long run.
We will be covering Vue.js computed properties in depth in the next post.