Tạo mới ứng dụng
- Vuejs có thể chạy dưới dạng một file html độc lập mà không cần cài đặt các phần mềm hay công cụ phát triển nào thêm. Sử dụng notepad để tạo một file hello.html với nội dung sau để bắt đầu ứng dụng Vue đầu tiên:
<meta charset="UTF-8"> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <div id="app"> <h1>{{ message }}</h1> </div> <script> new Vue({ el: '#app', data: { message: 'Hello' } }); </script> |
Sau khi tạo xong file, mở file bằng trình duyệt (chrome/firefox/edge …) để xem kết quả chương trình:

Chạy ứng dụng bằng cách mở file html với trình duyệt
- Cách thức hoạt động của ứng dụng:
- Ứng dụng Vuejs được khai báo bởi việc tạo mới một đối tượng Vue:
new Vue({...})
Trong đối tượng này có các thành phần cơ bản sau:
- el : Tên của element gốc (root) của ứng dụng. Toàn bộ nội dung html do Vue sinh ra sẽ được đặt bên trong element này.
- data: Dữ liệu của ứng dụng
- methods: Các phương thức của ứng dụng
- computed: Các thuộc tính thứ cấp (được tính từ các thuộc tính khác)
- created: Phương thức khởi tạo ứng dụng, được gọi sau khi ứng dụng khởi động xong
- watch: Các hàm lắng nghe sự kiện thay đổi của các biến trong phần data của ứng dụng
Chi tiết về các thành phần này sẽ được trình bày trong các phần sau
- Toàn bộ nội dung ứng dụng được đặt trong element gốc (root):
<div id="app">
<h1>{{ message }}</h1>
</div>
Nội dung bên trong element gốc này thực chất là một Vue template, không phải html thuần túy. Vue sử dụng template này kết hợp với phần data của ứng dụng để sinh ra html cuối cùng, sau đó mới hiển thị trên trình duyệt.
Ví dụ: {{ message }}, thực chất là một cú pháp của Vue template, nó sẽ được thay bằng giá trị của biến message trong phần data của ứng dụng:
data: {
message: 'Hello'
}
Do đó, nội dung html cuối cùng được hiển thị ra trình duyệt sẽ là:
<div id="app">
<h1>Hello</h1>
</div>
Gắn dữ liệu, thuộc tính cho các thẻ html
- Trong ứng dụng Vue đầu tiên, chúng ta thấy cách Vue sử dụng template để gắn dữ liệu từ phần data của ứng dụng vào các thẻ html trong template. Việc gắn dữ liệu này được gọi là data binding. Một số binding cơ bản:
- Gắn nội dung cho các thẻ static text (div, span, label, font, h1, h2, h3, …):
<div> {{ message }} </div>
<span> {{ message }} </span>
....
- Gắn dữ liệu cho các thẻ nhập liệu (input, select, textarea):
- Cách 1 : Sử dụng cú pháp v-bind để gắn thuộc tính vào cho element:
<input v-bind:value="message" />
Đây là cách gắn dữ liệu một chiều. Mỗi khi giá trị của biến message trong phần data của ứng dụng thay đổi thì thuộc tính value của thẻ input sẽ thay đổi theo. Tuy nhiên, khi người dùng thay đổi giá trị trong ô input này thì giá trị biến message không thay đổi.
Cú pháp v-bind:value có thể viết ngắn thành :value . Cú pháp này có tác dụng với cả các thuộc tính khác của các thẻ html (rows, cols, width, height, …). Một cách đơn giản, có thể hiểu v-bind:<attr> hay :<attr> sẽ được dịch thành thuộc tính <attr> của thẻ html:
+ v-bind:value, :value → value
+ v-bind:rows, :rows → rows
+ v-bind:cols, :cols → cols
Lưu ý: Giá trị của v-bind:<attr> là một biểu thức javascript, không phải một string.
- Cách 2: Sử dụng v-model để gắn thuộc tính vào cho element:
<input v-model="message" />
Đây là cách gắn dữ liệu 2 chiều (two-way-binding): Khi giá trị của biến message bị thay đổi trong chương trình, giá trị của thẻ input thay đổi theo, ngược lại khi người dùng thay đổi nội dung của ô input, giá trị của biến message cũng được cập nhật.
- Gắn css style cho các thẻ:
Cách gắn style cũng tương tự như gắn các thuộc tính html khác, có thể sử dụng v-bind:style hoặc :style. Tuy nhiên, lưu ý là giá trị của biểu thức truyền vào là một javascript object, không phải một string như style của css thông thường:
<input :style="{color: 'red', fontSize: '40px'}" />
Bên trong javascript object của :style, các thuộc tính css chứa ký tự gạch ngang ('-') được chuyển thành dạng camel case (ví dụ font-size → fontSize)
- Gắn css class cho các thẻ:
Tương tự, sử dụng v-bind:class hoặc :class để gắn css class cho các thẻ html. Nội dung của biểu thức truyền vào có một trong các dạng sau:
<div :class="['active', 'displayError']">
Trường hợp này truyền vào danh sách các css class mà thẻ html sẽ nhận.
<div :class="{ active: isActive, 'displayError': hasError }">
Trường hợp này truyền vào một danh sách kèm điều kiện của các css class. Trong trường hợp trên, thẻ div sẽ nhận class "active" nếu biến isActive (trong phần data) bằng true, và nhận class "displayError" nếu biến hasError (trong phần data) bằng true.
<div :class="[isActive ? 'active' : '', hasError? 'displayError' : '']">
Cách này tương tự cách 2.
Gắn hàm xử lý sự kiện cho các thẻ html
- Để gắn hàm xử lý sự kiện cho các thẻ html, dùng cú pháp
v-on:<event>="<eventHandler>"
Trong đó <event> là sự kiện cần xử lý (click, change, …), <eventHandler> là hàm xử lý sự kiện.
Ví dụ:
<meta charset="UTF-8"> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <div id="app"> <input v-model="message" v-on:change="inputChangeHandler()"/> <button v-on:click="buttonClickHandler()">Test</button> </div> <script> new Vue({ el: '#app', data: {message: ""}, methods: { inputChangeHandler() { alert(this.message); }, buttonClickHandler() { alert("Clicked"); } } }); </script>
|
Hiển thị có điều kiện
- Trong một số trường hợp, chương trình có thể hiển thị hoặc không hiển thị một/một số thẻ html tùy theo trạng thái của ứng dụng. Để thực hiện việc này, sử dụng cú pháp v-if và truyền vào một biểu thức điều kiện. Khi biểu thức bằng true, thẻ html sẽ được hiển thị, khi biểu thức bằng false, thẻ html sẽ bị ẩn.
Ví dụ:
<meta charset="UTF-8"> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <div id = "app"> <div v-if="show"> {{ message }} </div> <button v-on:click="show=true">Show</button> <button v-on:click="show=false">Hide</button> </div> <script> var vm = new Vue({ el: '#app', data: { show: true, message: "Hello" } }); </script> |
Hiển thị từ một danh sách
- Khi muốn hiển thị một danh sách các thẻ html từ một mảng dữ liệu (với các thẻ ul, table , …), có thể sử dụng cú pháp v-for và truyền vào một điều kiện lặp. Vue sẽ sinh ra một danh sách các thẻ html tương ứng với mảng dữ liệu truyền vào.
Ví dụ:
<meta charset="UTF-8"> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <div id="app"> <ul> <li v-for="st in students"> {{ st }} </li> </ul> </div> <script> new Vue({ el: '#app', data: { students: ["Nguyễn Văn A", "Nguyễn Văn B", "Nguyễn Văn C"] } }); </script> |
Trong trường hợp muốn lấy thêm chỉ số của vòng lặp có thể dùng:
v-for="(st, i) in students"
Ngoài ra, với v-for, nên truyền thêm thuộc tính :key để giúp Vue dễ update việc hiển thị danh sách khi dữ liệu thay đổi. Giá trị của :key cần duy nhất giữa các element với nhau, do đó thông thường sẽ sử dụng thuộc tính id của mỗi bản ghi trong tập dữ liệu. Nếu các bản ghi không có id, có thể dùng biến chỉ số vòng lặp để làm :key, ví dụ:
<meta charset="UTF-8"> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <div id="app"> <ul> <li v-for="(st, i) in students" :key="i"> {{i+1}} . {{ st }} </li> </ul> </div> <script> new Vue({ el: '#app', data: { students: ["Nguyễn Văn A", "Nguyễn Văn B", "Nguyễn Văn C"] } }); </script>
Thuộc tính thứ cấp (computed)
- Các biến trong phần data của ứng dụng có thể được dùng để gắn dữ liệu cho các thẻ html. Trong một số trường hợp chúng ta muốn tạo ra một thuộc tính trung gian từ phần data, sau đó mới gắn vào cho các thẻ, khi đó có thể dùng chức năng computed của Vue.
Ví dụ:
<meta charset="UTF-8"> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <div id="app"> <p>Họ: <input v-model="ho"/> </p> <p>Tên đệm: <input v-model="ten_dem"/> </p> <p>Tên: <input v-model="ten"/> </p> <span> {{ hoten }} </span> </div> <script> new Vue({ el: '#app', data: { ho: '', ten_dem: '', ten: '' }, computed: { hoten() { return this.ho + ' ' + this.ten_dem + ' ' + this.ten; } } }); </script> |
Ở ví dụ trên, thuộc tính hoten đã được sinh ra từ 3 trường dữ liệu trong phần data là : ho, ten_dem, ten
Theo dõi sự thay đổi các biến dữ liệu
- Trong một số trường hợp, chúng ta muốn theo dõi sự thay đổi của các biến dữ liệu (do người dùng nhập vào) để có các xử lý phù hợp. Để thực hiện việc này, có thể dùng chức năng watch của Vue.
Ví dụ:
<meta charset="UTF-8"> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <div id="app"> <input v-model="message"/> </div> <script> new Vue({ el: '#app', data: { message: '' }, watch: { message(newValue, oldValue) { alert("Old:" + oldValue + ",new:" + newValue); } } }); </script> |
Lưu ý là tên hàm trong phần watch phải trùng với tên biến trong phần data.
Hàm khởi tạo ứng dụng
- Sau khi ứng dụng khởi động xong, chúng ta có thể cần thực hiện một số thao tác khởi tạo (lấy dữ liệu từ server, thiết lập mặc định, …). Việc này được thực hiện trong hàm created của ứng dụng Vue.
Ví dụ:
<meta charset="UTF-8"> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <div id="app"> {{ message }} </div> <script> new Vue({ el: '#app', data: { message: '' }, created() { this.message = "Hello"; } }); </script> |
Lấy dữ liệu từ server
- Để lấy dữ liệu từ server, có thể dùng các thư viện như axios, hoặc dùng hàm fetch của javascript. Do hàm fetch là hàm async, do đó các hàm lấy dữ liệu cũng phải khai báo async, và khi gọi hàm phải có thêm await ở trước.
Ví dụ:
<meta charset="UTF-8"> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app"> <button v-on:click="getWeather()">Lấy thông tin thời tiết</button> <div v-if="weather"> <p><b>Thời tiết Hà Nội hiện tại</b></p> <p>Nhiệt độ : {{ weather.main.temp }} °C</p> <p>Độ ẩm : {{ weather.main.humidity }} %</p> <p>Áp suất khí quyển : {{ weather.main.pressure/1000 }} atm</p> </div> </div>
<script> new Vue({ el: "#app", data: { weather: null, server_url: "http://api.openweathermap.org/data/2.5/weather", location_id: "1581129", api_key: "d6477696b63c2e661af64eead58c11d9", },
methods: { async getWeather() { var url = this.server_url + `?id=${this.location_id}&units=metric&appid=${this.api_key}`; var response = await fetch(url); this.weather = await response.json(); } }, }); </script> |