用 Vue-CLI 一陣子後,因為有 SEO 的需求,所以決定改用 Nuxt.js。
雖然 Vue-CLI 也有套件 prerender-spa-plugin 可以做到預渲染的功能,但他無法預渲染動態路由,像是 /user/:id
這樣的路徑,因為預渲染是獲取已在的元素,但動態路由的元素狀態處於未知,所以無法取得對應的內容。當然,假使你的 Vue 專案都是靜態網頁,而且你也較熟悉 Vue-cli,那可以考慮用該套件即可,不需改用 Nuxt.js。
我們以往都是用 data()
存取資料,但 Nuxt.js 多了一個 asyncData
的選擇,將資料放在 asyncData
底下以達到從伺服器端渲染頁面的效果,可以改寫如下:
export default { asyncData() { return { weather: 'cold', degree: 5 } } }
頁面渲染前會執行 asyncData()
,並將值塞回 data()
內,詳細內容可參考官網的 asyncData() 介紹。
因此,可以改用 fetch
存取 components/
或 layouts/
裡的資料,改寫如下:
export default { data() { return { navDatas: [] } } async fetch() { this.navDatas = [ { name: "首頁", path: "/", }, { name: "產品", path: "#", children: [ { name: "產品一", path: "/product/product1", }, { name: "產品二", path: "/product/product2", } ] } ] } }
不過有看過一種說法是,asyncData()
適合用在覆蓋 data()
的資料上,fetch
則適合用在 vuex
上。所以我也不知道自己這樣寫是否有符合規範,如果有更好的方法歡迎留言給我!
這邊搭配 Bootstrap v5 來製作下拉選單,使用的是上方寫到的 navDatas[]
資料。我製作的是二層的下拉式選單 (dropdown menu),所以有比較多針對 class 的判斷式。
<template> <div class="collapse navbar-collapse" id="navbar"> <ul id="primary-navbar" class="navbar-nav ms-auto"> <li v-for="item in navData" :key="item.id" class="nav-item" :class="{ dropdown: item.children }"> <template v-if="item.children"> <nuxt-link :to="item.path" class="nav-link" :class="{ 'dropdown-toggle': item.children }" data-bs-toggle="dropdown">{{ item.name }}</nuxt-link> </template> <template v-else> <nuxt-link :to="item.path" class="nav-link" :class="{ 'dropdown-toggle': item.children }">{{ item.name }}</nuxt-link> </template> <ul v-if="item.children" class="dropdown-menu"> <li v-for="children in item.children" :key="children.id" :class="{ 'px-2': !children.path }"> <nuxt-link :to="children.path" class="dropdown-item" v-if="children.path">{{ children.name }}</nuxt-link> <span v-else>{{ children.name }}</span> </li> </ul> </li> </ul> </div> </template>
以上。
這篇不是教學,比較像是我寫 code 的筆記,因為對 Nuxt.js 不熟,很多觀念還沒有從頭看懂,所以也不敢亂教大家 XD。
後來因為有再搭配多國語系做選單,所以最後沒有使用 fetch
的方式產資料,有興趣的朋友可以參考以下這篇文章