For more advanced usage, refer to the official Vue.js documentation at https://vuejs.org/guide/extras/composition-api-faq.html
- Vue Instances
1.1. Creating Vue Instances
Every Vue application begins with creating a new Vue instance using the Vue constructor function:
const app = new Vue({
// Configuration options
})
The constructor accepts an object containing various Vue configuration options, including:
- el
- data
- methods
1.2. Templates and Elements
Each Vue instance needs to be associated with an HTML template for view rendering. This is specified using the el property:
<div id="app">
<!-- Vue will render here -->
</div>
const vueApp = new Vue({
el: "#app"
})
Vue will render based on the element with id "app". Features outside this element won't be accessible.
1.3. Data Handling
When a Vue instance is created, it automatically captures all properties defined in the data option for view rendering. Vue monitors these properties for changes, and when they occur, all related views are re-rendered. This is the "reactive" system.
<div id="app">
<input type="text" v-model="username" />
</div>
const userApp = new Vue({
el: "#app",
data: {
username: "alex"
}
})
The username value affects the input field, and changes in the input update the username property in the Vue instance.
1.4. Methods
Vue instances can define methods that are accessible with in the Vue scope:
<div id="app">
{{counter}}
<button @click="increment">Increase</button>
</div>
const counterApp = new Vue({
el: "#app",
data: {
counter: 0
},
methods: {
increment() {
this.counter++;
},
test() {
this.counter++;
}
}
})
1.5. Lifecycle Hooks
1.5.1. Lifecycle
Each Vue instance goes through a series of initialization steps when created: instance creation, template loading, rendering, etc. Vue provides lifecycle hooks (listener functions) for each state.
1.5.2. Hook Functions
For example, the created hook is called after the Vue instance is created:
<div id="app">
{{greeting}}
</div>
const vm = new Vue({
el: "#app",
data: {
greeting: ''
},
created() {
this.greeting = "Hello, World!";
}
})
1.5.3. The 'this' Context
Let's examine what the 'this' variable represents inside Vue. We'll log it during the created hook:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue Test</title>
</head>
<body>
<div id="vue-test">
<h1>Hello, {{name}}</h1>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<script>
const testVue = new Vue({
el: "#vue-test",
data: {
name: ""
},
created() {
this.name = "hello, world";
console.log(this);
}
});
</script>
</body>
</html>
- Directives
Directives are special attributes with a v- prefix. They expect a single JavaScript expression and their responsibility is to apply side effects to the DOM when the expression's value changes.
2.1. Interpolation Expressions
2.1.1. Mustache Syntax
Format:
{{ expression }}
Features:
- Supports JavaScript syntax and can call built-in functions (must return a value)
- Expressions must produce a result. For example, 1 + 1 is valid, but var a = 1 + 1; is not
- Can directly access data or functions defined in the Vue instance
Example:
<div id="app">{{username}}</div>
const app = new Vue({
el: "#app",
data: {
username: "John"
}
})
2.1.2. Interpolation Flicker
Using {{}} can cause issues on slow networks. When data hasn't loaded, the page shows the original {{}} and only displays the correct data after loading. This is called interpolation flicker.
2.1.3. v-text and v-html
Use v-text and v-html directives as alternatives to {{}}:
- v-text: Outputs data to element content. If the data contains HTML, it's treated as plain text
- v-html: Outputs data to element content. If the data contains HTML, it's rendered
<div id="app">
v-text: <span v-text="message"></span> <br/>
v-html: <span v-html="message"></span>
</div>
const vm = new Vue({
el: "#app",
data: {
message: "<h1>Hello, Summer!</h1>"
}
})
This avoids interpolation flicker and shows blank content when no data is available.
2.2. v-model
v-model enables two-way binding between the view and model. While v-text and v-html provide one-way binding, v-model allows both directions.
v-model is limited to certain element types:
- input
- select
- textarea
- checkbox
- radio
- components
Example:
<div id="app">
<input type="checkbox" v-model="languages" value="Java" />Java<br/>
<input type="checkbox" v-model="languages" value="PHP" />PHP<br/>
<input type="checkbox" v-model="languages" value="Swift" />Swift<br/>
<h1>
Selected: {{languages.join(',')}}
</h1>
</div>
const vm = new Vue({
el: "#app",
data: {
languages: []
}
})
Key points:
- Multiple checkboxes sharing a model result in an array type
- Radio buttons correspond to the input's value
- Input and textarea default to string type
- Select single corresponds to string, multiple to array
2.3. v-on (shorthand: @click)
2.3.1. Basic Usage
v-on directive binds events to DOM elements:
<div id="app">
<button v-on:click="counter++">Increase</button><br/>
<button v-on:click="decrease">Decrease</button><br/>
<h1>Counter: {{counter}}</h1>
</div>
const app = new Vue({
el: "#app",
data: {
counter: 1
},
methods: {
decrease() {
this.counter--;
}
}
})
2.3.2. Event Modifiers
Vue provides event modifiers to handle common event requirements like preventing default actions or stopping propagation:
- .stop: Stops event propagation
- .prevent: Prevents default event behavior
- .capture: Uses event capture mode
- .self: Only triggers if the element itself is the target
- .once: Executes only once
2.3.3. Key Modifiers
Vue allows adding key modifiers when listening to keyboard events:
<input v-on:keyup.13="submit">
<!-- Shorthand -->
<input @keyup.enter="submit">
Common key aliases:
- .enter
- .tab
- .delete (captures both "delete" and "backspace")
- .esc
- .space
- .up, .down, .left, .right
2.3.4. Modifier Combinations
Modifiers can be combined to trigger events only when specific keys are pressed:
<!-- Alt + C -->
<input @keyup.alt.67="clear">
<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
2.4. v-for
v-for directive renders lists by iterating over data:
2.4.1. Iterating Arrays
Syntax:
v-for="item in items"
Example:
<div id="app">
<ul>
<li v-for="user in users">
{{user.name}} : {{user.gender}} : {{user.age}}
</li>
</ul>
</div>
const app = new Vue({
el: "#app",
data: {
users: [
{name: 'Emma', gender: 'Female', age: 22},
{name: 'Jack', gender: 'Male', age: 25},
{name: 'Sophia', gender: 'Female', age: 28},
{name: 'Lucas', gender: 'Male', age: 24},
{name: 'Olivia', gender: 'Female', age: 26}
]
}
})
2.4.2. Array Index
To access the array index during iteration, specify a second parameter:
v-for="(item, index) in items"
2.4.3. Iterating Objects
v-for can also iterate over objects:
v-for="value in object"
v-for="(value, key) in object"
v-for="(value, key, index) in object"
2.4.4. Key Attribute
When updating rendered element lists, Vue uses an "in-place patch" strategy. To help Vue track each node's identity and reuse elements efficiently, provide a unique key attribute:
<ul>
<li v-for="(item, index) in items" :key="index"></li>
</ul>
2.5. v-if and v-show
2.5.1. Basic Usage
v-if conditional renders elements based on boolean expressions:
<div id="app">
<button @click="isVisible = !isVisible">Toggle</button><br/>
<h1 v-if="isVisible">
Hello
</h1>
</div>
const app = new Vue({
el: "#app",
data: {
isVisible: true
}
})
2.5.2. With v-for
When v-if and v-for appear together, v-for has higher priority. The list is iterated first, then conditions are evaluated.
2.5.3. v-else
The v-else directive represents an "else block" for v-if:
<div v-if="Math.random() > 0.5">
Success!
</div>
<div v-else>
Failure!
</div>
v-else must follow a v-if or v-else-if element.
2.5.4. v-show
v-show provides an alternative to conditionally display elements:
<h1 v-show="ok">Hello!</h1>
Difference: Elements with v-show are always rendered and remain in the DOM. v-show simply toggles the CSS display property.
2.6. v-bind
2.6.1. Binding Class Styles
To dynamically modify element attributes like class, use v-bind:
<div v-bind:class="isActive"></div> <!-- Shorthand: <div :class="isActive"></div> -->
Array syntax:
data: {
isActive: ['active', 'hasError']
}
Object syntax:
<div v-bind:class="{ active: isActive }"></div>
2.6.2. Shorthend
v-bind:class can be shortened to :class
2.7. Computed Properties
Computed properties help simplify complex expressions in templates:
const app = new Vue({
el: "#app",
data: {
birthdate: 1429032123201
},
computed: {
formattedBirth() {
const date = new Date(this.birthdate);
return date.getFullYear() + "-" + date.getMonth() + "-" + date.getDate();
}
}
})
Usage:
<div id="app">
<h1>Your birthdate is: {{formattedBirth}}</h1>
</div>
2.8. Watchers
Watchers monitor value changes and react accordingly:
<div id="app">
<input type="text" v-model="message">
</div>
const vm = new Vue({
el: "#app",
data: {
message: ""
},
watch: {
message(newVal, oldVal) {
console.log(newVal, oldVal);
}
}
})
- Componentization
In large applications, pages can be divided into reusable components. This avoids duplication and improves maintainability.
3.1. Defining Global Components
Global components are defined using Vue.component:
<div id="app">
<counter></counter>
</div>
Vue.component("counter", {
template: '<button @click="count++">Clicked {{ count }} times</button>',
data() {
return {
count: 0
}
}
})
const app = new Vue({
el: "#app"
})
3.2. Component Reusability
Components can be reused multiple times independently:
<div id="app">
<counter></counter>
<counter></counter>
<counter></counter>
</div>
Each component maintains its own state because data must be a function:
data: function() {
return {
count: 0
}
}
3.3. Local Registration
For less frequently used components, local registration is preferred:
const counter = {
template: '<button @click="count++">Clicked {{ count }} times</button>',
data() {
return {
count: 0
}
}
};
const app = new Vue({
el: "#app",
components: {
counter: counter
}
})
3.4. Component Communication
3.4.1. Parent to Child: Props
Parent components can pass data to child components using props:
Vue.component("introduction", {
template: '<h3>{{title}}</h3>',
props: ['title']
})
const app = new Vue({
el: "#app",
components: {
introduction: {
template: '<h1>{{title}}</h1>',
props: ['title']
}
}
})
3.4.2. Complex Data Passing
Components can receive complex data with type validation:
const itemList = {
template: '\
<ul>\
<li v-for="item in items" :key="item.id">{{item.id}} : {{item.name}}</li>\
</ul>\
',
props: {
items: {
type: Array,
default: []
}
}
}
3.4.3. Child to Parent Communication
Child components can communicate with parent components using events:
<div id="app">
<h2>Counter: {{counter}}</h2>
<counter :value="counter" @increment="increment" @decrement="decrement"></counter>
</div>
const counter = {
template: '\
<div>\
<button @click="increase">+</button> \
<button @click="decrease">-</button> \
</div>',
props: ['value'],
methods: {
increase() {
this.$emit("increment");
},
decrease() {
this.$emit("decrement");
}
}
}
const app = new Vue({
el: "#app",
data: {
counter: 0
},
methods: {
increment() {
this.counter++;
},
decrement() {
this.counter--;
}
},
components: {
counter: counter
}
})