Vue

2021.10.14

用 Nuxt.js 串接 data 做下拉式選單


前情提要

用 Vue-CLI 一陣子後,因為有 SEO 的需求,所以決定改用 Nuxt.js。

雖然 Vue-CLI 也有套件 prerender-spa-plugin 可以做到預渲染的功能,但他無法預渲染動態路由,像是 /user/:id 這樣的路徑,因為預渲染是獲取已在的元素,但動態路由的元素狀態處於未知,所以無法取得對應的內容。當然,假使你的 Vue 專案都是靜態網頁,而且你也較熟悉 Vue-cli,那可以考慮用該套件即可,不需改用 Nuxt.js。


fetch 與 asyncData 的選擇

我們以往都是用 data() 存取資料,但 Nuxt.js 多了一個 asyncData 的選擇,將資料放在 asyncData 底下以達到從伺服器端渲染頁面的效果,可以改寫如下:

export default {
  asyncData() {
    return {
      weather: 'cold',
      degree: 5
	}
  }
}

頁面渲染前會執行 asyncData(),並將值塞回 data() 內,詳細內容可參考官網的 asyncData() 介紹

asyncData() 使用注意

asyncData() 雖然看似好用,卻只能在 pages/ 資料夾底下的 *.vue 才有作用,如果你的 vue 檔案是放在 components/ layouts/ 底下,是無法利用 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 的方式產資料,有興趣的朋友可以參考以下這篇文章:

將 Nuxt.js 串接的資料改寫成多國語系

書接上回 上次提到如何用 Nuxt.js 串接 data 做下拉式選單,接下來會繼續沿用該資料,並將之改寫為多 […]

Read more


更多 Vue 相關文章

guest
0 則留言
Inline Feedbacks
View all comments
Copyright (C) MUKI space* / Reborn Theme All Rights Reserved.