NuxtJS Lifecycle

Nestsera Technology
6 min readSep 14, 2020

--

NuxtJS là một framework cấp tiến, được xây dựng trên VueJS, Nuxt vẫn sử dụng single file component của Vue (1 component = 1 file) và đã bổ sung thêm vài tính năng đặc biệt vào nó, trong bài viết này, chúng ta sẽ tìm hiểu xem vòng đời của 1 component trong Nuxt là như thế nào.

Nuxt lifecycle, hình ảnh từ tài liệu chính thức của Nuxt

Vue instance có vòng đời của nó thì Nuxt cũng vậy, được xây dựng lên từ Vue, Nuxt đã bổ sung rất nhiều hook khác để phục vụ cho việc phát triển các tính năng nâng cao khác, ta hãy cùng đi qua lần lượt từ trên xuống dưới theo như trong hình.

nuxtServerInit

Hook này chỉ đặc biệt có ở chế độ universal (server-side-rendering)

Nó là 1 VueX action ở trong root module (module VueX ở ngoài cùng) và chỉ được khai báo ở đó (~/store/index.js hoặc ~/store/actions.js). Hook này sẽ chạy đầu tiên và chỉ ở bên phía server-side khi ta vào một ứng dụng Nuxt. Hook này lấy tham số đầu tiên là biến context.

Phù hợp cho việc lấy token, auth instance từ trong cookie và lưu vào VueX-Store

Đối với chế độ spa (single-page-application) thì dù không có hook nuxtServerInit, nhưng bạn có thể replica nó bằng 1 global middleware và 1 biến nào đó đảm bảo là nó chỉ chạy 1 lần (ở đây dùng biến serverReady trong VueX state), chi tiết về middleware ở phần dưới:

Middleware

Khái niệm middleware là một hàm nào đó, chạy xen giữa vào, trước khi 1 giai đoạn nào đó được thực hiện trong app, nó cũng kha khá giống interceptor, nhưng bài viết này không đi quá sâu về sự khác biệt của 2 thuật ngữ ngày trong lập trình, ở đây middleware được thực hiện trước khi bạn enter vào 1 route (url).

Có 2 cách để bạn khai báo 1 middleware, middleware vô danh và định danh

Middleware định danh (named middleware) là khi ta tạo 1 file ở trong thư mục ~/middleware, có cú pháp xuất ra 1 hàm (export default function()).

và Nuxt sẽ tự biết file đó là 1 middleware, ta chỉ việc khai báo dùng middleware đó ở đâu mà thôi. Middleware định danh thì có 3 vị trí để sử dụng, toàn cục (Global), layout và trong phạm vi 1 route nhất định. Khi bạn vào 1 route thì có thể có nhiều middleware được thực hiện cùng lúc, theo thứ tự đó là:

● Khai báo ở global trước

● Khai báo ở layout sau

● Khai báo ở page component sau cùng

● Và cùng 1 chỗ mà nhiều middleware được sử dụng (mảng các string là tên các middleware) thì nó sẽ chạy từ trái sang phải

Middleware vô danh thì chỉ có một cách khai báo là ngay trong page component và nó tương đương với middleware định danh mà sử dụng tại page component thôi, cách khai báo khá giống các hook trong 1 Vue instance, tham số đầu tiên của nó cũng là context, và lưu ý là lúc này Vue instance còn chưa được khởi tạo nên không có đối tượng this ở đây nha

Đến đây mình thấy là có nhắc đến biến context khá nhiều, sợ các bạn mới vào không hiểu nên mình sẽ giải thích sơ là đại loại giống lúc chúng ta khai báo 1 hàm trong lập trình với các biến mặc định, thì context nó kiểu như biến mặc định vậy thôi

Có điều context nó có nhiều thứ hơn là mỗi cái chuỗi ‘something’, cụ thể thì vào cái link này chứ mình không có nói quá nhiều được: https://nuxtjs.org/api/context

Validate

Đây là 1 hook đặc biệt của Nuxt chạy sau tiến trình middleware, hook này bắt buộc phải được kết thúc bằng việc trả về true hoặc false, nếu true thì tiến trình sẽ được tiếp tục thực hiện, nếu false thì app sẽ throw về lỗi và bạn sẽ bị redirect về trang lỗi.

Cá nhân mình ít có khi dùng cái này, vì mình đa phần viết 1 cái middleware rồi áp dụng được cho nhiều route rồi, well, thì người ta cứ cung cấp cho mình 1 chức năng như vậy đó, ai lại đi áp đặt là dùng hay không đúng không? Tùy các bạn thôi.

asyncData

Đây là một hook khá đặc biệt của Nuxt chuyên dùng để lấy dữ liệu từ backend thông qua API vì nó có hỗ trợ bất đồng bộ, và hơn hết là giá trị nó trả về được trộn vào data của Vue instance

Ngay tại asyncData, Vue instance chưa được khởi tạo, bạn sẽ chưa truy cập được đối tượng this và nó nhận biến context là tham số đầu tiên, bạn có thể gọi API trực tiếp và trả về giá trị, hoặc gọi actions từ VueX và trả về giá trị

Tuy nhưng cá nhân mình không hay dùng hook này mà hay dùng hook fetch() sẽ được nói ở phía dưới

beforeCreate và created

2 hooks này được gọi lần lượt sau asyncData, điều đặc biệt là nó được gọi tại cả server-side và client-side (nếu bạn chọn chế độ universal), nếu muốn nó chạy chỉ 1 phía thì đơn giản là thêm một điều kiện kiểm tra như if (process.server) hoặc if (process.client) và được

Và mình sẽ không nói thêm về 2 hooks này vì nó thuộc về Vue instance lifecycle, các bạn có thể tham khảo tại đây: https://vuejs.org/v2/guide/instance.html#Lifecycle-Diagram

fetch

Công dụng tương tự như asyncData thì fetch cũng được sử dụng để lấy dữ liệu từ backend thông qua API, tuy nhưng nó không có trả về cái gì cả, dữ liệu lấy được phải được lưu vào VueX Store, và đó cũng là pattern mà mình ưu thích — VueX. Sau khi lấy xong dữ liệu thì mình sẽ dùng mapState, mapGetters để mang dữ liệu từ VueX store vào Vue instance để xài cho tiện.

Lưu ý là tác vụ gọi API hay gọi actions trong fetch đều phải sử dụng async await, nếu không thì sẽ xảy ra các vấn đề về bất đồng bộ không mong muốn.

Và hook fetch là hook duy nhất có thể được gọi lại:

Lưu ý là hook fetch kết thúc đến tận sau hook mounted, nên dù mounted được hoàn thành thì chưa chắc data sẽ ổn định (data vẫn có thể bị fetch làm thay đổi)

beforeMount và mounted

Hook mounted được gọi khi DOM đã được render và reactive, lúc này fetch chưa hoàn tất, nên có khả năng data vẫn bị thay đổi

Chi tiết hơn về 2 hook này, thao khảo tại: https://vuejs.org/v2/guide/instance.html#Lifecycle-Diagram

Kết thúc

Vậy đó là các hook cơ bản của NuxtJS cùng các ví dụ minh họa rất cụ thể, chúc các bạn dev vui!

Sưu tầm.

--

--