Trong quá trình phát triển ứng dụng, việc hiểu rõ về vòng đời của một component là điều vô cùng quan trọng. Vue.js là một trong những framework JavaScript cung cấp cho lập trình viên hệ thống lifecycle hooks phong phú để quản lý và kiểm soát cách mà các component được khởi tạo, cập nhật và gỡ bỏ. Trong bài viết này, hãy cùng ITviec tìm hiểu về lifecycle Vuejs.
Đọc bài viết để hiểu rõ hơn:
- Lifecycle Vuejs là gì?
- Lifecycle Hook Vuejs là gì?
- Các giai đoạn chính trong lifecycle Vuejs của component
- Các lifecycle hook đặc biệt khác trong Vuejs
- Các câu hỏi thường gặp về lifecycle Vuejs
Lifecycle VueJS là gì?
Mỗi khi một ứng dụng VueJS được tạo, một instance mới của component được tạo ra để giúp lập trình viên xây dựng hành vi mong muốn. Nó bao gồm các tùy chọn khác nhau như templates, methods, props, watchers, lifecycles, data và nhiều thứ khác.
Lifecycle (vòng đời) của một component là quá trình từ lúc được tạo ra, gắn vào DOM, được mounted (gắn kết), cập nhật dữ liệu, cho đến khi bị hủy bỏ. Việc hiểu rõ vòng đời này giúp lập trình viên thêm code vào các giai đoạn khác nhau để thực hiện các tác vụ như:
- Khởi tạo dữ liệu: Lấy dữ liệu từ server, khởi tạo các biến.
- Gắn kết DOM: Thực hiện các thao tác với DOM sau khi component được render.
- Cập nhật giao diện: Cập nhật giao diện khi dữ liệu thay đổi.
- Dọn dẹp: Hủy bỏ các listener, timer trước khi component bị xóa khỏi DOM.
Đọc thêm: VueJS là gì? Hướng dẫn ứng dụng hiệu quả Vue.js trong lập trình
Lifecycle Hook VueJS là gì?
Lifecycle hook trong Vue.js là các phương thức được gọi tại những thời điểm khác nhau trong vòng đời của một component. Mỗi component trong Vue.js trải qua một vòng đời từ khi được khởi tạo, render, cập nhật, cho đến khi bị gỡ bỏ khỏi DOM. Trong quá trình này, Vue cung cấp các hook để lập trình viên có thể can thiệp và thực hiện các thao tác tại các giai đoạn cụ thể của vòng đời component.
Các móc (hook) trong vòng đời của một component:
Lifecycle Hook (Móc vòng đời) | Mô tả |
Các giai đoạn chính trong vòng đời của component Vuejs | |
beforeCreate | Xảy ra trước tất cả hook trong vòng đời khác. |
created | Component được khởi tạo và bạn có thể truy cập các thuộc tính của instance component. |
beforeMount | Component chưa được gắn vào DOM, vì vậy bạn không thể truy cập các phần tử DOM. |
mounted | Component đã được gắn vào cây DOM, cho phép truy cập các phần tử DOM. |
beforeUpdate | Xảy ra khi hệ thống phản ứng của Vue phát hiện có sự thay đổi cần một lần render mới. |
updated | Xảy ra ngay sau khi cây DOM đã được cập nhật. |
beforeUnmount | Xảy ra ngay trước khi một component bị gỡ bỏ khỏi DOM. |
unmounted | Xảy ra sau khi một component bị gỡ bỏ khỏi DOM. |
Các hook đặc biệt khác | |
errorCaptured | Xảy ra khi có lỗi trong một component con hoặc component con cháu. |
renderTracked | Xảy ra khi một hàm render được thiết lập để theo dõi hoặc giám sát một component phản ứng. |
renderTriggered | Xảy ra khi có thay đổi trong một component phản ứng được theo dõi, dẫn đến một lần render mới. |
activated | Xảy ra khi một component động được lưu trong bộ nhớ cache được thêm vào (nhưng đã có trong DOM). |
deactivated | Xảy ra khi một component động được lưu trong bộ nhớ cache bị loại bỏ (nhưng không bị gỡ khỏi DOM). |
serverPrefetch | Xảy ra trong quá trình render phía server (SSR). |
Cùng tìm hiểu về các giai đoạn của lifecycle Vuejs trong nội dung bên dưới.
Giai đoạn 1: Creation – Khởi tạo
Before create
beforeCreate là giai đoạn đầu tiên trong quá trình tạo ra một instance Vue. Tại giai đoạn này, instance vẫn chưa hoàn thiện và chúng ta chưa thể truy cập vào dữ liệu, phương thức, hay các thuộc tính tính toán của component. Hãy hình dung như bạn đang chuẩn bị nguyên liệu để làm bánh, nhưng chưa bắt đầu nhào bột.
Lifecycle hook beforeCreate được gọi trước khi Vue thiết lập các thuộc tính phản ứng (reactive), phương thức, và các trình lắng nghe sự kiện. Điều này có nghĩa là bạn không nên cố gắng truy cập vào các phần tử thuộc về component từ lifecycle hook này.
Lưu ý: Bạn có thể sử dụng beforeCreate để thiết lập một số biến toàn cục hoặc thực hiện các tác vụ khởi tạo ban đầu khác. Tuy nhiên, không nên cố gắng thao tác với DOM hoặc truy cập vào dữ liệu của component.
Ví dụ: Sử dụng hook beforeCreate để tạo một cảnh báo, ghi vào console, và thử thay đổi thuộc tính dữ liệu ‘text’ nhưng không thành công.
App.vue
<template> <h1>The 'beforeCreate' Lifecycle Hook</h1> <p>We can see the console.log() message from 'beforeCreate' lifecycle hook, but there is no effect from the text change we try to do to the Vue data property, because the Vue data property is not created yet.</p> <button @click="this.activeComp = !this.activeComp">Add/Remove Component</button> <div> <comp-one v-if="activeComp"></comp-one> </div> </template> <script> export default { data() { return { activeComp: false } } } </script> <style> #app > div { border: dashed black 1px; border-radius: 10px; padding: 10px; margin-top: 10px; background-color: lightgreen; } #pResult { background-color: lightcoral; display: inline-block; } </style>
CompOne.vue
<template> <h2>Component</h2> <p>This is the component</p> <p id="pResult">{{ text }}</p> </template> <script> export default { data() { return { text: '...' } }, beforeCreate() { this.text = 'initial text'; console.log("beforeCreate: The component is not created yet."); } } </script>
main.js
import { createApp } from 'vue' import App from './App.vue' import CompOne from './components/CompOne.vue' const app = createApp(App) app.component('comp-one', CompOne) app.mount('#app')
Ảnh minh hoạ 1 → Ảnh minh hoạ 2
Created
Giai đoạn created là thời điểm mà một component Vue đã được khởi tạo hoàn chỉnh. Tại đây, tất cả các dữ liệu, phương thức, thuộc tính tính toán (computed properties) và các trình lắng nghe sự kiện (event listeners) đã sẵn sàng để sử dụng. Hãy hình dung như một chiếc bánh đã được nhào xong và các nguyên liệu đã được chuẩn bị đầy đủ, sẵn sàng để đưa vào lò nướng.
Lifecycle hook created được gọi sau khi component khởi tạo, xảy ra sau “beforeCreate” và trước “beforeMount” vì đây là thời điểm thích hợp để:
- Truy cập dữ liệu: Bạn có thể truy cập và thao tác với dữ liệu của component.
- Gọi các phương thức: Bạn có thể gọi các phương thức đã được định nghĩa trong component.
- Thực hiện các tác vụ khởi tạo: Ví dụ, thực hiện các yêu cầu HTTP để lấy dữ liệu từ server và cập nhật dữ liệu của component.
Tuy nhiên, bạn không nên cố gắng truy cập trực tiếp vào các phần tử DOM từ giai đoạn created vì DOM chưa được gắn vào (mount) vào trang web tại thời điểm này.
Ví dụ: Sử dụng hook created để thay đổi thuộc tính dữ liệu ‘text’.
App.vue
<template> <h1>The 'created' Lifecycle Hook</h1> <p>We can see the console.log() message from 'created' lifecycle hook, and the text change we try to do to the Vue data property works, because the Vue data property is already created at this stage.</p> <button @click="this.activeComp = !this.activeComp">Add/Remove Component</button> <div> <comp-one v-if="activeComp"></comp-one> </div> </template> <script> export default { data() { return { activeComp: false } } } </script> <style> #app > div { border: dashed black 1px; border-radius: 10px; padding: 10px; margin-top: 10px; background-color: lightgreen; } #pResult { background-color: lightcoral; display: inline-block; } </style>
CompOne.vue
<template> <h2>Component</h2> <p>This is the component</p> <p id="pResult">{{ text }}</p> </template> <script> export default { data() { return { text: '...' } }, created() { this.text = 'initial text'; console.log("created: The component just got created."); } } </script>
main.js
import { createApp } from 'vue' import App from './App.vue' import CompOne from './components/CompOne.vue' const app = createApp(App) app.component('comp-one', CompOne) app.mount('#app')
Ảnh minh hoạ 1 → Ảnh minh hoạ 2
Giai đoạn 2: Mount – Thao tác với cây DOM
Giai đoạn gắn kết (Mounting) là giai đoạn mà component Vue được kết nối với DOM (Document Object Model), tức là nó được hiển thị trên màn hình. Trong giai đoạn này, Vue sẽ thay thế một phần tử trong DOM bằng cấu trúc HTML được định nghĩa trong template của component.
Before mount
Trước khi component được gắn vào DOM, Vue sẽ kiểm tra xem template có sẵn hay không. Giai đoạn này chủ yếu dùng để chuẩn bị một số việc trước khi component được hiển thị. Chúng ta nên tránh cố gắng truy cập các phần tử DOM từ hook vòng đời beforeMount, vì các phần tử DOM không thể truy cập được cho đến khi component được gắn kết.
Ví dụ: Sử dụng hook mounted để đặt con trỏ chuột vào trường nhập liệu ngay khi component được gắn vào.
App.vue
<template> <h1>The 'beforeMount' Lifecycle Hook</h1> <p>We can see the console.log() message from the 'beforeMount' lifecycle hook, but the text change we try to do to the 'pEl' paragraph DOM element does not work, because the 'pEl' paragraph DOM element does not exist yet at this stage.</p> <button @click="this.activeComp = !this.activeComp">Add/Remove Component</button> <div> <comp-one v-if="activeComp"></comp-one> </div> </template> <script> export default { data() { return { activeComp: false } } } </script> <style> #app > div { border: dashed black 1px; border-radius: 10px; padding: 10px; margin-top: 10px; background-color: lightgreen; } #pEl { background-color: lightcoral; display: inline-block; } </style>
CompOne.vue
<template> <h2>Component</h2> <p>This is the component</p> <p ref="pEl" id="pEl">We try to access this text from the 'beforeMount' hook.</p> </template> <script> export default { beforeMount() { console.log("beforeMount: This is just before the component is mounted."); this.$refs.pEl.innerHTML = "Hello World!"; // <-- We cannot reach the 'pEl' DOM element at this stage } } </script>
main.js
import { createApp } from 'vue' import App from './App.vue' import CompOne from './components/CompOne.vue' const app = createApp(App) app.component('comp-one', CompOne) app.mount('#app')
Ảnh minh hoạ 1 → Ảnh minh hoạ 2
Mounted
Sau khi component đã được gắn vào DOM, Vue sẽ gọi hook mounted. Đây là thời điểm thích hợp để bạn thực hiện các thao tác liên quan đến DOM, như thêm sự kiện, truy cập các phần tử DOM, hoặc thực hiện các yêu cầu AJAX để lấy dữ liệu.
Ví dụ: Sử dụng hook mounted để đặt con trỏ vào bên trong trường nhập liệu ngay khi component được gắn vào DOM.
App.vue
<template> <h1>The 'mounted' Lifecycle Hook</h1> <button @click="this.activeComp = !this.activeComp">Create component</button> <div> <comp-one v-if="activeComp"></comp-one> </div> </template> <script> export default { data() { return { activeComp: false } } } </script> <style scoped> div { border: dashed black 1px; border-radius: 10px; padding: 20px; margin: 10px; width: 400px; background-color: lightgreen; } </style>
CompOne.vue
<template> <h2>Component</h2> <p>Right after this component is added to the DOM, the mounted() function is called and we can add code to that mounted() function. In this example, an alert popup box appears after this component is mounted.</p> <p><strong>Note:</strong> The reason that the alert is visible before the component is visible is because the alert is called before the browser gets to render the component to the screen.</p> </template> <script> export default { mounted() { alert("The component is mounted!"); } } </script>
main.js
import { createApp } from 'vue' import App from './App.vue' import CompOne from './components/CompOne.vue' const app = createApp(App) app.component('comp-one', CompOne) app.mount('#app')
Ảnh minh hoạ 1 → Ảnh minh hoạ 2
Giai đoạn 3: Update – Cập nhật
Giai đoạn cập nhật bao gồm các hook beforeUpdated và updated, khá hữu ích trong việc gỡ lỗi, thay đổi trạng thái phản ứng của component hoặc xảy ra render lại.
Before update
Đây là thời điểm ngay trước khi giao diện được cập nhật. Bạn có thể tận dụng giai đoạn này để kiểm tra xem dữ liệu mới có hợp lệ không hoặc thực hiện một số chuẩn bị trước khi giao diện thay đổi.
Một điều đặc biệt về hook beforeUpdate là bạn có thể thực hiện thay đổi cho ứng dụng mà không cần kích hoạt bản cập nhật mới, nhờ đó tránh được vòng lặp vô hạn. Đó là lý do tại sao không nên thực hiện thay đổi cho dữ liệu reactive trong hook updated, vì với hook đó, một vòng lặp vô hạn sẽ được tạo ra.
Ví dụ: Sử dụng hook beforeUpdate để đếm số lần một lần cập nhật được kích hoạt.
App.vue
<template> <h1>Lifecycle Hook 'beforeUpdate' Example</h1> <p>When the 'sliderVal' property gets a new value from the slider, a new render is triggered because the page must be updated.</p> <p>The 'beforeUpdate' lifecycle hook is used to count how many times a new page render is triggered.</p> <p>Move image: <input type="range" v-model="sliderVal" min="0" max="200"> {{ sliderVal }} px</p> <div id="wrapper"> <img src="/img_apple.svg" v-bind:style="{ left: sliderVal + 'px' }"> </div> <p>Rendered <span>{{ renderCount }}</span> times.</p> </template> <script> export default { data() { return { sliderVal: 50, renderCount: 0 } }, beforeUpdate() { this.renderCount++; } } </script> <style scoped> #wrapper { height: 100px; width: 300px; position: relative; border: solid black 3px; } img { height: 100px; scale: 1; background-color: lightblue; position: absolute; top: 0;
main.js
import { createApp } from 'vue' import App from './App.vue' const app = createApp(App) app.mount('#app')
Updated
Hook Updated là giai đoạn sau khi giao diện đã được cập nhật xong. DOM được cập nhật dưới hook này và các hoạt động phụ thuộc vào DOM đã có thể thực hiện như thêm sự kiện, cuộn đến một phần tử cụ thể,…
Ví dụ: Sử dụng hook updated để ghi một thông điệp vào console mỗi khi cây DOM được cập nhật.
App.vue
<template> <h1>Lifecycle Hook 'updated' Example</h1> <p>Using the 'updated' lifecycle hook to count how many times the page has been rendered.</p> <p>Slider value <input type="range" v-model="sliderVal"> {{ sliderVal }}</p> <p>In this example, we write the render count to the console, because making changes to the view would re-activate the updated hook and create an infinite loop.</p> </template> <script> export default { data() { return { sliderVal: 50, renderCount: 0 } }, updated() { this.renderCount++; console.log('Updated ' + this.renderCount + ' times.') } } </script> <style scoped> span { background-color: lightgreen; } </style>
main.js
import { createApp } from 'vue' import App from './App.vue' const app = createApp(App) app.mount('#app')
Giai đoạn 4: Unmount – Gỡ bỏ
Unmount là một giai đoạn trong vòng đời của một component Vue, diễn ra khi component đó bị xóa khỏi DOM. Nói cách khác, khi một component không còn được hiển thị trên giao diện người dùng nữa, thì nó sẽ trải qua giai đoạn unmount.
Before Unmount
Đây là giai đoạn trước khi component bị gỡ bỏ khỏi DOM. Ở giai đoạn này, bạn có thể thực hiện các thao tác như hủy bỏ các sự kiện, ngừng lắng nghe thay đổi dữ liệu, hoặc dọn dẹp tài nguyên như bộ hẹn giờ, yêu cầu API đang chờ, hoặc kết nối WebSocket.
Tại thời điểm “beforeUnmount”, component vẫn hoàn toàn hoạt động. Tất cả các thuộc tính, computed properties, và methods vẫn có thể truy cập được. Khi một component cha bị unmount, tất cả các component con của nó cũng sẽ bị unmount.
Ví dụ: Sử dụng hook beforeUnmount để tạo một cảnh báo với nội dung lấy từ bên trong một phần tử <p>.
App.vue
<template> <h1>The 'beforeUnmount' Lifecycle Hook</h1> <p>As we can see in the alert box, the text inside the p-tag is still accessible in the 'beforeUnmount' hook, right before the 'unmount' hook.</p> <button @click="this.activeComp = !this.activeComp">{{ btnText }}</button> <div> <comp-one v-if="activeComp"></comp-one> </div> </template> <script> export default { data() { return { activeComp: true } }, computed: { btnText() { if(this.activeComp) { return 'Remove component' } else { return 'Add component' } } } } </script> <style scoped> div { border: dashed black 1px; border-radius: 10px; padding: 20px; margin: 10px; width: 400px; background-color: lightgreen; } </style>
CompOne.vue
<template> <h2>Component</h2> <p ref="pEl">Strawberries!</p> </template> <script> export default { beforeUnmount() { alert("beforeUnmount: The text inside the p-tag is: " + this.$refs.pEl.innerHTML); } } </script>
main.js
import { createApp } from 'vue' import App from './App.vue' import CompOne from './components/CompOne.vue' const app = createApp(App) app.component('comp-one', CompOne) app.mount('#app')
Ảnh minh hoạ 1 → Ảnh minh hoạ 2
Unmounted
Đây là giai đoạn khi component đã hoàn toàn bị gỡ khỏi DOM. Trong Vue.js 3, bạn có thể sử dụng hook unmounted để kiểm tra hoặc thực hiện thao tác khi DOM đã bị xóa.
Ví dụ: Sử dụng hook unmounted để tạo một cảnh báo khi component bị gỡ bỏ khỏi DOM.
App.vue
<template> <h1>Lifecycle Hooks</h1> <button @click="this.activeComp = !this.activeComp">{{ btnText }}</button> <div> <comp-one v-if="activeComp"></comp-one> </div> </template> <script> export default { data() { return { activeComp: true } }, computed: { btnText() { if(this.activeComp) { return 'Remove component' } else { return 'Add component' } } } } </script> <style scoped> div { border: dashed black 1px; border-radius: 10px; padding: 20px; margin: 10px; width: 400px; background-color: lightgreen; } </style>
CompOne.vue
<template> <h2>Component</h2> <p>When this component is removed from the DOM tree, the unmounted() function is called and we can add code to that function. In this example we create an alert popup box when this component is removed.</p> </template> <script> export default { unmounted() { alert("The component is removed (unmounted)!"); } } </script>
main.js
import { createApp } from 'vue' import App from './App.vue' import CompOne from './components/CompOne.vue' const app = createApp(App) app.component('comp-one', CompOne) app.mount('#app')
Ảnh minh hoạ 1 → Ảnh minh hoạ 2
Các lifecycle hook Vuejs đặc biệt
errorCaptured
Hook vòng đời errorCaptured được gọi khi có lỗi xảy ra trong một component con hoặc component con cháu. Hook này có thể được sử dụng để xử lý lỗi, ghi nhật ký, hoặc hiển thị lỗi cho người dùng.
Khi sử dụng hook errorCaptured, lưu ý không kích hoạt việc render lại component nơi lỗi xuất phát, vì ó thể dẫn đến vòng lặp vô hạn. Thông tin về lỗi được cung cấp qua ba tham số trong hàm errorCaptured() gồm: Lỗi xảy ra; Component kích hoạt lỗi; Loại nguồn của lỗi.
Hành vi mặc định khi lỗi xảy ra là lỗi sẽ lan truyền, hoặc “bong bóng lên”, từ component gây ra lỗi. Một lỗi trong component sẽ truyền lên component cha, và tiếp tục truyền lên các cấp cao hơn, cuối cùng hiển thị dưới dạng thông báo lỗi trong bảng điều khiển (console). Bằng cách trả về false trong hàm errorCaptured(), lỗi sẽ không truyền lên component cha (ngừng lan truyền) và cũng không xuất hiện dưới dạng thông báo lỗi trong bảng điều khiển.
Việc xử lý lỗi cũng có thể được thiết lập thông qua hàm app.config.errorHandler.
Ví dụ: Sử dụng hook vòng đời errorCaptured để phát hiện lỗi từ thành phần con và tạo cảnh báo cho người dùng.
App.vue
<template> <h1>The 'errorCaptured' Lifecycle Hook</h1> <p>Whenever there is an error in a child component, the errorCaptured() function is called on the parent.</p> <p>When the button inside the component is clicked, a method will run that tries to do changes to a $refs object that does not exist. This creates an error in the component that triggers the 'errorCaptured' lifecycle hook in the parent, and an alert box is displayed with information about the error.</p> <p>After clicking "Ok" in the alert box you can see the error in the browser console.</p> <div> <comp-one></comp-one> </div> </template> <script> export default { errorCaptured() { alert("An error occurred"); } } </script> <style> #app > div { border: dashed black 1px; border-radius: 10px; padding: 10px; margin-top: 10px; background-color: lightgreen; } </style>
CompOne.vue
<template> <h2>Component</h2> <p>This is the component</p> <button @click="generateError">Generate Error</button> </template> <script> export default { methods: { generateError() { this.$refs.objEl.innerHTML = "hi"; } } } </script>
main.js
import { createApp } from 'vue' import App from './App.vue' import CompOne from './components/CompOne.vue' const app = createApp(App) app.component('comp-one', CompOne) app.mount('#app')
renderTracked
Hook renderTracked được chạy khi một hàm render được thiết lập để theo dõi hoặc giám sát một component phản ứng. (Component phản ứng là component có thể thay đổi). Hook renderTracked được dùng để hỗ trợ quá trình gỡ lỗi và chỉ khả dụng ở chế độ phát triển (development mode).
Ví dụ: Sử dụng hook vòng đời renderTracked để tạo cảnh báo khi thành phần phản ứng được khởi tạo.
App.vue
<template> <h1>The 'renderTracked' Lifecycle Hook</h1> <p>The 'renderTracked' lifecycle hook is used for debugging.</p> <p><mark>This example only works in development mode, so to see the hook run, you must copy this code and run it on you own computer in development mode.</mark></p> <div> <comp-one></comp-one> </div> </template> <style scoped> div { border: dashed black 1px; border-radius: 10px; padding: 20px; margin-top: 10px; background-color: lightgreen; } </style>
main.js
import { createApp } from 'vue' import App from './App.vue' import CompOne from './components/CompOne.vue' const app = createApp(App) app.component('comp-one', CompOne) app.mount('#app')
Ảnh minh hoạ 1 → Ảnh minh hoạ 2
renderTriggered
Hook vòng đời renderTriggered được chạy khi một component phản ứng được theo dõi có sự thay đổi, từ đó kích hoạt một lần render mới, giúp màn hình cập nhật với các thay đổi mới nhất.
Hook renderTriggered được thiết kế để sử dụng trong quá trình gỡ lỗi và chỉ khả dụng ở chế độ phát triển (development mode).
Ví dụ: Sử dụng hook vòng đời renderTriggered để hiển thị cảnh báo mỗi khi quá trình kết xuất được kích hoạt.
App.vue
<template> <h1>The 'renderTriggered' Lifecycle Hook</h1> <p>The 'renderTriggered' lifecycle hook is used for debugging.</p> <p><mark>This example only works in development mode, so to see the hooks run, you must copy this code and run it on you own computer in development mode, and click the 'Add One' button.</mark></p> <div> <comp-one></comp-one> </div> </template> <style scoped> div { border: dashed black 1px; border-radius: 10px; padding: 20px; margin-top: 10px; background-color: lightgreen; } </style>
CompOne.vue
<template> <h2>Component One</h2> <p>This is a component.</p> <button @click="counter++">Add One</button> <p>{{ counter }}</p> </template> <script> export default { data() { return { counter: 0 } }, renderTriggered(evt) { console.log("renderTriggered: ",evt) alert("renderTriggered"); } } </script>
main.js
import { createApp } from 'vue' import App from './App.vue' import CompOne from './components/CompOne.vue' const app = createApp(App) app.component('comp-one', CompOne) app.mount('#app')
Ảnh minh hoạ 1 → Ảnh minh hoạ 2
Activated
Hook Activated được sử dụng đặc biệt cho các component trong template keep-alive. Nó rất hữu ích cho các nhà phát triển để giữ nguyên trạng thái của một component ngay cả sau khi chuyển sang một component khác. Mỗi khi template keep-alive được chuyển đổi với một component, các hook activated và deactivated được bật.
Ví dụ: Sử dụng hook vòng đời activated để ghi lại mỗi khi hook activated được gọi.
App.vue
<template> <h1>The 'activated' Lifecycle Hook</h1> <p>In this example for the 'activated' hook we check if the component is cached properly with <KeepAlive>.</p> <p>If the component is cached properly with <KeepAlive> we expect the 'mounted' hook to run once the first time the component is included (must be added to the DOM the first time), and we expect the 'activated' hook to run every time the component is included (also the first time).</p> <button @click="this.activeComp = !this.activeComp">Include component</button> <div> <KeepAlive> <comp-one v-if="activeComp"></comp-one> </KeepAlive> </div> </template> <script> export default { data() { return { activeComp: false } } } </script> <style scoped> div { border: dashed black 1px; border-radius: 10px; padding: 20px; margin-top: 10px; background-color: lightgreen; } </style>
CompOne.vue
<template> <h2>Component</h2> <p>Below is a log with every time the 'mounted' or 'activated' hooks run.</p> <ol ref="olEl"></ol> <p>You can also see when these hooks run in the console.</p> </template> <script> export default { mounted() { console.log("mounted"); const liEl = document.createElement("li"); liEl.innerHTML = "mounted"; this.$refs.olEl.appendChild(liEl); }, activated() { console.log("activated"); const liEl = document.createElement("li"); liEl.innerHTML = "activated"; this.$refs.olEl.appendChild(liEl); } } </script> <style> li { background-color: lightcoral; width: 5em; } </style>
main.js
import { createApp } from 'vue' import App from './App.vue' import CompOne from './components/CompOne.vue' const app = createApp(App) app.component('comp-one', CompOne) app.mount('#app')
Ảnh minh hoạ 1 → Ảnh minh hoạ 2
Deactivated
Như đã giải thích trong hook trước, hook deactivated cũng được sử dụng để giữ cho các component của template đó hoạt động. Hook này được sử dụng để xác định khi nào một component của template này bị tắt.
Ví dụ: Sử dụng hook vòng đời deactivated để ghi lại mỗi lần hook deactivated được gọi.
App.vue
<template> <h1>The 'deactivated' Lifecycle Hook</h1> <p>Using the 'deactivated' hook to log when the 'deactivated' hook is called.</p> <button @click="this.activeComp = !this.activeComp">Include component</button> <div> <KeepAlive> <comp-one v-if="activeComp"></comp-one> </KeepAlive> </div> </template> <script> export default { data() { return { activeComp: false } } } </script> <style scoped> div { border: dashed black 1px; border-radius: 10px; padding: 20px; margin-top: 10px; background-color: lightgreen; } </style>
CompOne.vue
<template> <h2>Component</h2> <p>Below is a log with every time the 'deactivated' hook runs.</p> <ol> <li v-for="x in hookLog">{{ x }}</li> </ol> <p>You can also see when the 'deactivated' hook runs in the console.</p> </template> <script> export default { data() { return { hookLog: [] } }, deactivated() { console.log("deactivated") this.hookLog.push("deactivated"); } } </script> <style> li { background-color: lightcoral; width: 5em; } </style>
main.js
import { createApp } from 'vue' import App from './App.vue' import CompOne from './components/CompOne.vue' const app = createApp(App) app.component('comp-one', CompOne) app.mount('#app')
Ảnh minh hoạ 1 → Ảnh minh hoạ 2
serverPrefetch
Hook vòng đời serverPrefetch chỉ xảy ra trong quá trình render phía server (SSR). Chúng thường được sử dụng để lấy dữ liệu, trong trường hợp cần thực hiện việc này ở phía server.
Hook serverPrefetch hoạt động như một hàm bất đồng bộ (asynchronous function), do đó nếu nó trả về một promise, server sẽ chờ cho đến khi promise được giải quyết trước khi tiến hành render component.
Ví dụ:
export default { data() { return { data: null, }; }, async serverPrefetch() { const response = await fetch("https://random-data-api.com/api/v2/users"); this.data = await response.json(); } };
Các câu hỏi thường gặp về lifecycle VueJS
Khi nào nên sử dụng lifecycle hook?
Lifecycle hook là một công cụ mạnh mẽ để thêm hành vi tùy chỉnh vào các instance hoặc component Vue tại các giai đoạn khác nhau trong vòng đời của chúng. Chúng đặc biệt hữu ích cho những việc như lấy dữ liệu từ API, dọn dẹp trước khi một component bị hủy, phản ứng với các thay đổi trong props hoặc dữ liệu.
Tôi có thể tìm hiểu thêm về lifecycle VueJS ở đâu?
Bạn có thể tìm hiểu thêm về lifecycle hook Vuejs tại các nguồn tài liệu chính thức của nhà phát hành chẳng hạn Document chính thức từ VueJS về Hooks và Document chính thức từ VueJs về Options: Lifecycle.
Tổng kết lifecycle VueJS
Vuejs sẽ hỗ trợ bạn rất nhiều trong hành trình trở thành lập trình viên giỏi. Bên cạnh việc hiểu rõ về “Vuejs tutorial” trong bài viết trước, nắm bắt và sử dụng thành thạo “lifecycle Vuejs” cũng mang lại lợi ích lớn. Giờ đây, bạn có thể hình dung quy trình làm việc tốt hơn và khởi tạo các component theo thời gian và cách thức mà mình mong muốn.