Skip to main content

Vue Basics 1

All content in this article comes from the book "Vue.js in Action"

Please view full code on github

v-modelโ€‹

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello world</title>
</head>
<body>
<div id="app">
<input type="text" v-model="name" placeholder="your name">
<h1>Hello,{{ name }}</h1>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
var app = new Vue({
<!-- #app is the id of an element -->
el:'#app',
data: {
name: ''
}
})
</script>
</body>
</html>

To save space, all subsequent code in this article will only provide the content within the body tag.

v-html, v-preโ€‹

<div id="app">
<span v-html="link"></span>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
var app = new Vue({
el:'#app',
data: {
link: '<a href="#">This is a link</a>'
}
})
</script>
<div id="app">
<span v-pre>{{Just for displaying double curly braces}}</span>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
var app = new Vue({
el:'#app',
data: ''
})
</script>

Ternary Operator, Arithmetic Operationsโ€‹

<div id="app">
<!-- Vue.js only supports single expressions, not statements and flow control -->
{{ number / 10 }}
{{ isOK ? 'Y' : 'N' }}
{{ text.split(',').reverse().join(',') }}
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
var app = new Vue({
el:'#app',
data: {
number: 100,
isOK: false,
text: '123,456'
}
})
</script>

Filtersโ€‹

<div id="app">
{{ date | formatDate}}<!-- Use filter to format time -->
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
var padDate = function(value) {
return value < 10 ? '0' + value : value
};
var app = new Vue({
el:'#app',
data: {
date : new Date()
},
filters: {
formatDate: function(value) {
var date = new Date(value);
var year = date.getFullYear();
var month = padDate(date.getMonth()+1);
var day = padDate(date.getDate());
var hours = padDate(date.getHours());
var minutes = padDate(date.getMinutes());
var seconds = padDate(date.getSeconds());
return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds
}
},
mounted: function() {
var _this = this;// Declare a variable pointing to the Vue instance this, to ensure consistency of scope
this.timer = setInterval(function() {
_this.date = new Date(); // Modify data
}, 1000);
},
beforeDestroy: function() {
if(this.timer) {
clearInterval(this.timer);
}
}
})
</script>

Filters should be used for simple text transformations. If you want to implement more complex data transformations, you should use computed properties.

v-bindโ€‹

<div id="app">
<a v-bind:href="url">Link</a>
<img v-bind:src="imgUrl">
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
var app = new Vue({
el:'#app',
data: {
url : 'https://www.github.com',
imgUrl : 'https://gitee.com/jack541/repo-for-pic-go/raw/master/img/image-20220102162032176.png'
}
})
</script>

The following two sentences are equivalent:

<a v-bind:href="url">Link</a>

<a :href="url">Link</a>

v-onโ€‹

<div id="app">
<p v-if="show">This is a paragraph of text</p>
<button v-on:click="handleClose">Click to hide</button>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
var app = new Vue({
el:'#app',
data: {
show : true
},
methods: {
handleClose: function(){
if (this.show == true)
this.show = false;
else
this.show = true;
}
}
})
</script>

The following two sentences are equivalent:

<button v-on:click="handleClose">Click to hide</button>

<button @click="handleClose">Click to hide</button>

Usage of computed propertiesโ€‹

<div id="app">
{{ reversedText }}
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
var app = new Vue({
el:'#app',
data: {
text: '123,456'
},
computed: {
reversedText: function() {
return this.text.split(',').reverse().join(',');
}
}
})
</script>
<div id="app">
Total Price:{{ prices }}
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
var app = new Vue({
el:'#app',
data: {
package1: [
{
name: 'iPhone 13 128G',
price: 5999,
count: 3
},{
name: 'iPad mini6',
price: 3799,
count: 5
}
],
package2: [
{
name: 'iPhone 13 pro 256G',
price: 8999,
count: 3
},{
name: 'Mac Pro intel i9 1TB SDD 32G RAM',
price: 21999,
count: 1
}
]
},
computed: {
prices : function() {
var prices = 0;
for (var i = 0; i < this.package1.length; i++) {
prices += this.package1[i].price * this.package1[i].count;
}
for (var i = 0; i < this.package2.length; i++) {
prices += this.package2[i].price * this.package2[i].count;
}
return prices;
}
}
})
</script>

setter getterโ€‹

<div id="app">
Name:{{ fullName }}
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
var app = new Vue({
el:'#app',
data: {
firstName: 'jack',
lastName: 'green'
},
computed: {
fullName: {
//getter Used for reading
get: function () {
return this.firstName + ' ' + this.lastName;
},
// setter Triggered when writing
set: function (newValue) {
var names = newValue.split(' ');
this.firstName = names[0];
this.lastName = names[names.length - 1];
}
}
}
})
</script>

Computed Cachingโ€‹

Computed properties are cached based on their dependencies. A computed property will only re-evaluate when some of its responsive dependencies have changed.

<div id="app">
<!-- Note that reversedText here is a method, so it needs () -->
{{ reversedText() }}
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
var app = new Vue({
el:'#app',
data: {
text: '123,456'
},
methods: {
reversedText: function() {
return this.text.split(',').reverse().join(',');
}
}
})
</script>

Using v-bind to toggle class attributesโ€‹

<div id="app">
<div :class="{ 'active': isActive, 'error': isError }"></div>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
var app = new Vue({
el:'#app',
data: {
isActive: true,
isError: false
}
})
</script>

When the expression of :class is too long or the logic is complex, you can also bind a computed property. This is a very friendly and common usage. Generally, when there are more than two conditions, you can use data or computed.

<div id="app">
AA<div :class="classes"></div>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
var app = new Vue({
el:'#app',
data: {
isActive: true,
error: null
},
computed: {
classes: function() {
return {
active: this.isActive && !this.error,
'text-fail': this.error && this.error.type === 'fail'
}
}
}
})
</script>

Array Syntaxโ€‹

  • data definition
<div id="app">
<div :class="[{ 'active' : isActive }, errorCls]"></div>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
var app = new Vue({
el:'#app',
data: {
isActive: true,
errorCls: 'error'
},
})
</script>
  • computed definition
<div id="app">
<button :class="classes"></button>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
var app = new Vue({
el:'#app',
data: {
size: 'large',
disabled: true
},
computed: {
classes: function() {
return [
'btn',
{
// Define btn size, use size dimension when not empty
['btn-' + this.size]: this.size != '',
// Define whether the button is available
['btn-disabled']: this.disabled
}
]
}
}
})
</script>

NOTES: Using computed properties to dynamically set class names for elements is often used in business, especially when writing reusable components. Therefore, in the development process, if the expression is long or the logic is complex, computed properties should be used as much as possible.

Binding Styleโ€‹

<div id="app">
<div :style="styles">Text</div>
<!-- To handle multiple objects, use array syntax, styleA is equivalent to a styles element in data -->
<!-- <div :style="[styleA, styleB] " >Text</d iv> -->
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
var app = new Vue({
el:'#app',
data: {
styles :{
color: 'red',
fontSize: 14+'px'
}
}
})
</script>

In actual business, the array syntax of :style is not commonly used because it can usually be written in one object; and the more commonly used one should be computed properties.

v-cloakโ€‹

<div id="app" v-cloak>
{{ message }}
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
var app = new Vue({
el:'#app',
data: {
message: 'Page is loading...'
}
});

</script>

v-onceโ€‹

The function is to define that its element or component is rendered only once, including all child nodes of the element or component.

<div id="app">
<span v-once> {{ message }}</span>
<div v-once>
<span> {{ message }} </span>
</div>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
var app = new Vue({
el:'#app',
data: {
message: 'This is a text'
}
})
</script>

v-if v-else-if v-elseโ€‹

<div id="app">
<p v-if="status === 1"> Display this line when status is 1</p>
<p v-else-if="status === 2"> Display this line when status is 2</p>
<p v-else>Otherwise display this line</p>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
var app = new Vue({
el:'#app',
data: {
status: 1
}
})
</script>

v-else-if must follow v-if, v-else must follow v-else-if or v-if. When the expression value is true, the current element/component and all its child nodes will be rendered, and removed when false.

template Reusing Elementsโ€‹

<div id="app">
<template v-if="type === 'name'">
<label>Username:</label>
<input placeholder="Enter username">
</template>
<template v-else>
<label>Email:</label>
<input placeholder="Enter email">
</template>
<button @click="handleToggleClick">Toggle input type</button>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
var app = new Vue({
el:'#app',
data: {
type: 'name'
},
methods: {
handleToggleClick: function () {
this.type = this.type === 'name' ? 'mail' : 'name';
}
}
})
</script>

If you do not want to reuse the input box, you can use the key attribute provided by Vue.js, which allows you to decide whether to reuse the element. The value of key must be unique.

<template v-if="type === 'name'">
<label>Username:</label>
<input placeholder="Enter username" key="name-input">
</template>
<template v-else>
<label>Email:</label>
<input placeholder="Enter email" key="mail-input">
</template>

v-showโ€‹

<div id="app">
<p v-show="status === 1">Display this line when status is 1</p>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
var app = new Vue({
el:'#app',
data: {
status: 2
}
})
</script>

v-show cannot be used on <template>.

If the initial value of expression v-if is false, the element/component will not be rendered at the beginning, and will only be compiled when the condition becomes true for the first time. And v-show is just a simple CSS attribute toggle, it will be compiled regardless of whether the condition is true or not. In contrast, v-if is more suitable for scenarios where conditions do not change frequently, because its switching cost is relatively high, while v-show is suitable for frequent switching conditions.

v-forโ€‹

<div id="app">
<ul>
<li v-for="book in books">{{ book.name }}</li>
<!-- <li v-for="book of books">{{ book.name }}</li> -->
</ul>
</div>
<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>
new Vue({
el: '#app',
data: {
books: [
{name : 'ใ€ŠVue.js in Actionใ€‹'},
{name : 'ใ€ŠJavaScript: The Good Partsใ€‹'},
{name : 'ใ€ŠProfessional JavaScript for Web Developersใ€‹'}
]
}
})
</script>

Reference: Book "Vue.js in Action"

Agreement
The code part of this work is licensed under Apache License 2.0 . You may freely modify and redistribute the code, and use it for commercial purposes, provided that you comply with the license. However, you are required to:
  • Attribution: Retain the original author's signature and code source information in the original and derivative code.
  • Preserve License: Retain the Apache 2.0 license file in the original and derivative code.
The documentation part of this work is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License . You may freely share, including copying and distributing this work in any medium or format, and freely adapt, remix, transform, and build upon the material. However, you are required to:
  • Attribution: Give appropriate credit, provide a link to the license, and indicate if changes were made.
  • NonCommercial: You may not use the material for commercial purposes. For commercial use, please contact the author.
  • ShareAlike: If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original.