- vừa được xem lúc

Vue 2 Nâng Cao – Làm Chủ Vue Lifecycle Hook, Router, Vuex và Component Communication

0 0 3

Người đăng: Do Anh Tuan

Theo Viblo Asia

1. Vue Lifecycle Hooks – Vòng đời của một Component

Vue cung cấp các "hooks" giúp bạn thực hiện hành động tại các giai đoạn khác nhau của vòng đời component.

export default { data() { return { message: 'Xin chào Vue!' }; }, created() { console.log('Component đã được tạo (created)'); }, mounted() { console.log('Component đã gắn vào DOM (mounted)'); }, destroyed() { console.log('Component đã bị hủy (destroyed)'); }
}

📌 Giải thích:

  • created(): Chạy sau khi component được khởi tạo, chưa render ra DOM.
  • mounted(): Chạy sau khi component đã được mount vào DOM.
  • destroyed(): Chạy khi component bị hủy.

2. Vue Router – Routing trong SPA (Single Page Application)

Vue Router là một thư viện chính thức của Vue.js giúp bạn tạo ứng dụng nhiều trang (SPA) mà không cần tải lại trang (reload). Khi bạn chuyển giữa các "trang", Vue Router sẽ thay đổi URL và hiển thị component tương ứng mà không làm trình duyệt reload.

SPA = Single Page Application: chỉ có 1 file HTML, nhưng giao diện nhiều phần như "trang chủ", "giới thiệu", "liên hệ", v.v.

2.1 Cài đặt:

Nếu bạn dùng dự án Vue CLI:

npm install vue-router

2.2 Cấu hình Vue Router:

Bạn cần tạo một file riêng để định nghĩa các route (đường dẫn), ví dụ: router.js

Bước 1: Tạo các Component dùng làm trang

// Home.vue <template> <div> <h2>Trang chủ</h2> <p>Chào mừng bạn đến với Vue!</p> </div>
</template>
// About.vue <template> <div> <h2>Giới thiệu</h2> <p>Đây là trang giới thiệu về ứng dụng.</p> </div>
</template>

Bước 2: Tạo file router.js

// router.js import Vue from 'vue';
import VueRouter from 'vue-router'; import Home from './components/Home.vue';
import About from './components/About.vue'; Vue.use(VueRouter); // Kích hoạt plugin const routes = [ { path: '/', component: Home }, { path: '/about', component: About }
]; const router = new VueRouter({ mode: 'history', // Dùng history API (không có hash #) routes
}); export default router; 

📌Giải thích:

  • path: Đường dẫn URL.
  • component: Component sẽ hiển thị khi truy cập vào path đó.
  • mode: 'history': Giúp URL trông đẹp hơn, bỏ dấu #.

Bước 3: Tích hợp router vào Vue

// main.js import Vue from 'vue';
import App from './App.vue';
import router from './router'; new Vue({ router, render: h => h(App),
}).$mount('#app');

2.3 Điều hướng và hiển thị component

Trong App.vue:

<template> <div> <h1>Ứng dụng Vue Router</h1> <nav> <router-link to="/">Trang chủ</router-link> | <router-link to="/about">Giới thiệu</router-link> </nav> <router-view></router-view> </div>
</template>

📌 Giải thích:

  • <router-link>: Thẻ dùng để điều hướng (giống <a> nhưng không reload trang).
  • to="/": Đường dẫn tương ứng với route.
  • <router-view>: Nơi component được hiển thị tương ứng với route đang truy cập.

2.4 Điều hướng bằng JavaScript

Bạn có thể điều hướng bằng code:

this.$router.push('/about');

Hoặc quay lại:

this.$router.go(-1);

2.5 Dynamic Route (Route có tham số)

Bước 1: Tạo component User.vue

// User.vue <template> <div> <h2>Trang người dùng</h2> <p>Đây là người dùng có ID: {{ userId }}</p> </div>
</template> <script>
export default { computed: { userId() { // Lấy giá trị id từ route param return this.$route.params.id; } }
}
</script>

📌 Giải thích:

  • this.$route.params.id: lấy giá trị id từ URL.
  • Dùng computed để hiển thị userId mỗi khi URL thay đổi.

Bước 2: Cập nhật router

// router.js import Vue from 'vue';
import VueRouter from 'vue-router';
import User from './components/User.vue';
import Home from './components/Home.vue'; Vue.use(VueRouter); const routes = [ { path: '/', component: Home }, { path: '/user/:id', component: User } // Route có tham số
]; const router = new VueRouter({ mode: 'history', routes
}); export default router;

📌 Giải thích:

  • :id là tham số động. Bạn có thể dùng bất kỳ tên nào, ví dụ :slug, :name, vân vân và mây mây
  • Khi người dùng truy cập /user/5, thì id = 5

Bước 3: Thêm link điều hướng

Trong App.vue:

<template> <div> <nav> <router-link to="/">Trang chủ</router-link> <router-link to="/user/1">User 1</router-link> // Đây là người dùng có ID: 1 <router-link to="/user/2">User 2</router-link> // Đây là người dùng có ID: 2 </nav> <router-view></router-view> </div>
</template>

3. Vuex – Quản lý trạng thái toàn cục

Cài đặt:

npm install vuex

Cấu hình:

import Vue from 'vue';
import Vuex from 'vuex'; Vue.use(Vuex); const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment(state) { state.count++; } }, actions: { asyncIncrement({ commit }) { setTimeout(() => { commit('increment'); }, 1000); } }, getters: { doubleCount: state => state.count * 2 }
}); new Vue({ el: '#app', store
});

Sử dụng trong component:

<template> <div> <p>Số đếm: {{ count }}</p> <button @click="increment">Tăng</button> </div>
</template> <script>
export default { computed: { count() { return this.$store.state.count; } }, methods: { increment() { this.$store.commit('increment'); } }
}
</script>

📌 Giải thích:

  • state: Dữ liệu dùng chung.
  • mutations: Cập nhật state (đồng bộ).
  • actions: Gọi xử lý bất đồng bộ.
  • getters: Tính toán từ state.

4. Giao tiếp component (Component Communication)

4.1 Truyền dữ liệu từ Cha → Con (qua props)

// ParentComponent.vue <template> <div> <h2>Cha</h2> <ChildComponent :message="parentMessage" /> </div>
</template> <script>
import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, data() { return { parentMessage: "Chào con ta là cha" } }
}
</script>
// ChildComponent.vue: <template> <div> <p>Tin nhắn từ cha: {{ message }}</p> // Result: Tin nhắn từ cha: Chào con ta là cha </div>
</template> <script>
export default { props: ['message']
}
</script>

📌 Giải thích:

  • :message="parentMessage" là truyền dữ liệu xuống con
  • Con nhận dữ liệu qua props

4.2 Truyền dữ liệu từ Con → Cha (qua $emit)

// ParentComponent.vue: <template> <div> <h2>Cha</h2> <p>Tin nhắn từ con: {{ messageFromChild }}</p> // Result: Tin nhắn từ con: Xin chào tôi là con! <ChildComponent @childMessage="receiveFromChild" /> </div>
</template> <script>
import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, data() { return { messageFromChild: '' } }, methods: { receiveFromChild(data) { this.messageFromChild = data; } }
}
</script>
// ChildComponent.vue <template> <div> <button @click="sendToParent">Gửi dữ liệu cho cha</button> </div>
</template> <script>
export default { methods: { sendToParent() { this.$emit('childMessage', 'Xin chào tôi là con!'); } }
}
</script>

📌 Giải thích:

  • this.$emit('childMessage', dữ liệu) dùng để gửi sự kiện kèm dữ liệu lên component cha
  • Cha nghe bằng @childMessage="..."

4.3 tiếp giữa các component không liên quan (dùng Event Bus)

Tạo file event-bus.js

// event-bus.js import Vue from 'vue';
export const EventBus = new Vue();

Component A (gửi dữ liệu):

<template> <button @click="sendData">Gửi dữ liệu</button>
</template> <script>
import { EventBus } from './event-bus'; export default { methods: { sendData() { EventBus.$emit('myEvent', 'Dữ liệu từ Component A'); } }
}
</script>

Component B (nhận dữ liệu):

<template> <div> <p>Dữ liệu nhận: {{ received }}</p> </div>
</template> <script>
import { EventBus } from './event-bus'; export default { data() { return { received: '' } }, created() { EventBus.$on('myEvent', (data) => { this.received = data; }); }, beforeDestroy() { EventBus.$off('myEvent'); // tránh memory leak }
}
</script>

📌 Giải thích:

  • EventBus là đối tượng trung gian truyền sự kiện giữa các component không có quan hệ cha – con.
  • Dùng EventBus.$emit() để gửi, EventBus.$on() để nhận.

4.4 Truyền dữ liệu từ cháu → ông (nhiều cấp)

Vue 2 không hỗ trợ provide/inject mạnh như Vue 3, nhưng vẫn dùng được: Grandparent.vue

<template> <div> <h2>Ông</h2> <ParentComponent /> </div>
</template> <script>
import ParentComponent from './ParentComponent.vue';
export default { provide() { return { grandpaMessage: "Dữ liệu từ Ông" } }, components: { ParentComponent }
}
</script>

ChildComponent.vue (cháu)

<template> <div> <p>Nhận từ ông: {{ grandpaMessage }}</p> </div>
</template> <script>
export default { inject: ['grandpaMessage']
}
</script>

📌 Giải thích:

  • provide/inject giúp chia sẻ dữ liệu qua nhiều cấp component.

Tài liệu tham khảo

https://v2.vuejs.org/

Bình luận

Bài viết tương tự

- vừa được xem lúc

Một vài thủ thuật CSS mà chính Frontend có thể còn chưa biết (Phần 30)

. Hello xin chào mọi người, mình đã trở lại và tiếp tục với phần 30 của series về Một vài thủ thuật CSS mà chính Frontend có thể còn chưa biết. Bắt đầu thôi nào.

0 0 48

- vừa được xem lúc

5 câu hỏi phỏng vấn Frontend giúp bạn tự tin hơn khi sử dụng bất đồng bộ trong Javascript

Một trong những điều khó khăn khi học Javascript là promises. Chúng không dễ hiểu và có thể cần một vài hướng dẫn và một thời gian kha khá để vận dụng chúng.

0 0 106

- vừa được xem lúc

Một vài thủ thuật CSS mà chính Frontend có thể còn chưa biết (Phần 31)

Hello xin chào mọi người, mình đã trở lại và tiếp tục với phần 31 của series về Một vài thủ thuật CSS mà chính Frontend có thể còn chưa biết. Bắt đầu thôi nào.

0 0 46

- vừa được xem lúc

Những lý do khiến mình thích CSS custom properties hơn SASS variables?

Halo các bạn,. Lại là mình với một bài post liên quan tới chủ đề Front-end đây Mình còn nhớ hồi mình bắt đầu tìm hiểu và bị SASS lôi cuốn, mình đã nghĩ rằng mình sẽ chẳng bao giờ cần dùng đụng tới CSS

0 0 91

- vừa được xem lúc

Usability là gì? Những lưu ý khi thiết kế Usability

Usability là một yếu tố quan trọng trong sự thành bại của sản phẩm. Thật đáng tiếc khi sản phẩm làm ra ưu việt về tính năng, nhưng lại không được người dùng tiếp nhận, đơn giản chỉ vì khó sử dụng.

0 0 38

- vừa được xem lúc

7 Repos cho Front-End mà chính bạn còn không biết là bạn cần nó

. Những repos chẳng mấy khi được nhắc đến nhưng lại giúp bạn build mọi thứ nhanh hơn và tốt hơn nhiều. Chúng ta đang sống trong một thời đại có sẵn các công cụ và tài nguyên hoàn hảo, chúng chỉ cách t

0 0 40