Nuxt內導航欄的兩種實現方式

方式一 | 通過嵌套路由實現

在pages頁面根據nuxt的路由規則,建立頁面

1. 創建文件目錄及文件


根據規則,如果要創建子路由,子路由的文件夾名字,必須和父路由名字相同
所以,我們的文件夾也為index,index文件夾需要一個默認的頁面不然nuxt的路由規則就不能正確匹配頁面

一級路由是根路由
二級路由是index,user,默認進入index路由

下面是router頁面自動生成的路由

{
    path: "/",
    component: _93624e48,
    children: [{
      path: "",
      component: _7ba30c26,
      name: "index"
    }, {
      path: "user",
      component: _6934afa7,
      name: "index-user"
    }]
  }

2. html頁面增加nutx-child配合子路由跳轉

<template>
  <div class="container">
    <div>
      <logo />
      <h1 class="title">
        nuxt-demo
      </h1>
      // 直接訪問路由
      <!-- <nuxt-link to="/users">用戶列表</nuxt-link> -->
      // 通過push的方式直接訪問路由路徑
      <!-- <el-button @click="$router.push('/users')">用戶列表</el-button> -->
      // 通過push的方式,同時用對象的方式訪問路由
      <el-button @click="$router.push({name: 'index'})">首頁</el-button>
      <el-button @click="$router.push({name: 'index-user'})">用戶詳情</el-button>
    </div>
    // nuxt規定的子路由插槽
    <nuxt-child></nuxt-child>
  </div>
</template>

這裡就拿官方demo改了一下,可以看到,切換路由的時候,只有子路由頁面是變換的,父路由部分是沒有變換的

方式二 | 創建公共組件實現

這個方法是需要用到vuex的,當然了,如果嫌麻煩,用storage也行

在components內創建公共組件

1.在pages文件夾創建頁面,一個主頁,一個用戶頁面,一個活動頁面


創建頁面的過程就不一一細說了,具體就是文件夾下面一個index.vue,router就會讀這個index為路由指定的頁面

我們看下.nuxt文件夾下面的router.js頁面


這就是建立好的路由

2. 創建公共組件


這裡偷個懶,用的element的導航欄組件

<template>
  <div id="nav-wrapper">
    <el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect">
      <el-menu-item index="1" @click="$router.push({name: 'index'})">首頁</el-menu-item>
      <el-menu-item index="3" @click="$router.push({name: 'users'})">用戶頁面</el-menu-item>
      <el-menu-item index="4" @click="$router.push({name: 'active'})">活動頁面</el-menu-item>
    </el-menu>
  </div>
</template>

3. 在所有路由頁面導入創建的公共組件

<template>
  <div class="container">
    <div>
      <logo />
      <h1 class="title">
        nuxt-demo
      </h1>
      <navBar />
    </div>
  </div>
</template>

<script>
import Logo from '~/components/Logo.vue'
import navBar from '~/components/nav.vue'

export default {
  components: {
    Logo,
    navBar
  }
}
</script>

<style>

這樣就完成了第一步,我們看下預覽

問題出現了,雖然我們的路由變換了,但是導航欄的狀態確沒有同步,因為路由跳轉的時候,組件狀態會刷新,所以這個時候,需要共享狀態,所以,我這裡用的是vuex

4. 使用vuex同步導航欄狀態

直接在store文件夾內進行添加就行,nuxt里推薦的兩種vuex使用方法

第一種是普通創建

第二種是模組化創建

這裡我選的是第二種方式,我也建議使用這種,因為方便維護,各種狀態一目了然

我們看下目錄結構,這裡和在vue使用的vuex目錄是一樣的


這裡就不一一詳細說明每個文件內容了,本次重點是使用vuex來同步狀態

我們把狀態同步到vuex中,這樣每次頁面進來的時候,直接讀取vuex中的數據,就可以同步導航欄狀態欄了

4.1 vuex使用報錯

store/index.js should export a method that returns a Vuex

instance.vuex在nuxt中是需要導出一個store實例
我們這裡需要改動一下store文件下的index頁面


我們繼續回到導航欄組件內

<template>
  <div id="nav-wrapper">
    <el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect">
      <el-menu-item index="1" @click="$router.push({name: 'index'})">首頁</el-menu-item>
      <el-menu-item index="3" @click="$router.push({name: 'users'})">用戶頁面</el-menu-item>
      <el-menu-item index="4" @click="$router.push({name: 'active'})">活動頁面</el-menu-item>
    </el-menu>
  </div>
</template>

<script>
  import {mapGetters, mapMutations} from 'vuex'
  export default{
    data() {
      return {
        activeIndex: '1',
        activeIndex2: '1'
      };
    },
    computed: {
      ...mapGetters([
        'barIndex'
      ])
    },
    methods: {
      ...mapMutations({
        'change_index': 'CHANGE_INDEX'
      }),
      handleSelect(key, keyPath) {
        console.log(key, keyPath);
        this.activeIndex = key
        // 每次切換導航欄,會把當前狀態同步到vuex中
        this.change_index(this.activeIndex)
      }
    },
    created() {
      if (this.barIndex) { // 判斷vuex內是否有上一次存儲的數據,有就同步到當前狀態
        this.activeIndex = this.barIndex
      }
      console.log('vuex', this.activeIndex)
    }
  }
</script>

這樣,我們就已經可以同步導航欄狀態了

如果有更好的方式,希望大牛們在評論區不吝賜教

Tags: