文章

Vue Router 與 Vuex 集成

在 Vue 3 的應用開發中,Vue RouterVuex 是兩個常用的核心庫,分別負責應用的路由管理和狀態管理。當你的應用變得複雜時,將這兩個工具結合使用能夠大大提升開發效率和用戶體驗。下面我們將介紹如何將 Vue RouterVuex 集成,並使用它們來管理應用的狀態和路由。

1. 為什麼要將 Vue Router 與 Vuex 集成?

當應用中有路由跳轉時,經常會需要對某些路由進行權限控制(如需要用戶登錄才能訪問),或者根據不同路由顯示不同的數據,這時就需要 Vuex 和 Vue Router 進行配合。通過將這兩者集成,能夠實現以下功能:

  • 基於用戶狀態進行路由訪問控制:如登錄狀態控制、角色權限控制。
  • 在路由變更時更新 Vuex 狀態:當路由改變時,Vuex 可以跟隨更新應用的狀態。
  • 根據 Vuex 狀態進行條件性的路由跳轉

2. 基礎步驟:集成 Vue Router 和 Vuex

1. 安裝 Vue Router 和 Vuex

首先,你需要確保已經安裝了 Vue Router 和 Vuex:

1
npm install vue-router@next vuex@next

2. 設置 Vuex Store 和 Vue Router

在你的項目中,分別設置 Vuex 的 store 和 Vue Router 的路由。

  • Vuex Store 設置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import { createStore } from 'vuex';

const store = createStore({
  state: {
    isAuthenticated: false, // 用於跟蹤登錄狀態
    user: null
  },
  mutations: {
    login(state, user) {
      state.isAuthenticated = true;
      state.user = user;
    },
    logout(state) {
      state.isAuthenticated = false;
      state.user = null;
    }
  }
});

export default store;
  • Vue Router 設置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { createRouter, createWebHistory } from 'vue-router';
import Home from './views/Home.vue';
import Login from './views/Login.vue';
import Dashboard from './views/Dashboard.vue';

const routes = [
  { path: '/', name: 'Home', component: Home },
  { path: '/login', name: 'Login', component: Login },
  { path: '/dashboard', name: 'Dashboard', component: Dashboard }
];

const router = createRouter({
  history: createWebHistory(),
  routes
});

export default router;

3. 在主應用中使用 Vuex 和 Vue Router

main.js 中引入 Vuex 和 Vue Router,並將它們掛載到 Vue 應用中:

1
2
3
4
5
6
7
8
9
import { createApp } from 'vue';
import App from './App.vue';
import store from './store';
import router from './router';

const app = createApp(App);
app.use(store);
app.use(router);
app.mount('#app');

這樣,你的應用已經基礎集成了 Vue Router 和 Vuex。


3. 基於 Vuex 狀態進行路由控制

1. 路由守衛控制訪問權限

可以使用 Vue Router 的 全局導航守衛(navigation guards)來控制哪些路由需要登錄才能訪問,並根據 Vuex 中的 isAuthenticated 狀態來進行跳轉控制。

範例:

1
2
3
4
5
6
7
8
9
10
11
12
router.beforeEach((to, from, next) => {
  const isAuthenticated = store.state.isAuthenticated;

  // 檢查目標路由是否需要認證
  if (to.name === 'Dashboard' && !isAuthenticated) {
    // 如果未認證,則跳轉到登錄頁面
    next({ name: 'Login' });
  } else {
    // 如果已認證,則繼續導航
    next();
  }
});

在這裡,我們使用 router.beforeEach() 全局守衛,對於某些需要登錄的頁面(如 Dashboard),如果用戶未登錄(即 isAuthenticatedfalse),則重定向到登錄頁面。

2. 登錄後重定向

在登錄操作完成後,我們可以更新 Vuex 的狀態,並將用戶重定向到之前嘗試訪問的受保護路由,這樣可以提供更加流暢的用戶體驗。

範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<template>
  <div>
    <form @submit.prevent="login">
      <input type="text" v-model="username" placeholder="用戶名" />
      <button type="submit">登錄</button>
    </form>
  </div>
</template>

<script>
export default {
  data() {
    return {
      username: ''
    };
  },
  methods: {
    login() {
      // 模擬登錄成功
      this.$store.commit('login', this.username);

      // 重定向到之前嘗試訪問的頁面,默認重定向到 Dashboard
      const redirect = this.$route.query.redirect || '/dashboard';
      this.$router.push(redirect);
    }
  }
};
</script>

登錄成功後,我們通過 this.$store.commit('login') 更新 Vuex 狀態,並通過 this.$router.push() 將用戶重定向到他們原本想訪問的頁面。


4. 根據 Vuex 狀態更新 UI 和跳轉

1. 根據 Vuex 狀態控制 UI

根據 Vuex 狀態來動態顯示不同的導航鏈接或按鈕,例如登錄和登出按鈕。

範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<template>
  <nav>
    <ul>
      <li><router-link to="/">Home</router-link></li>
      <li v-if="!isAuthenticated"><router-link to="/login">Login</router-link></li>
      <li v-if="isAuthenticated"><router-link to="/dashboard">Dashboard</router-link></li>
      <li v-if="isAuthenticated"><button @click="logout">Logout</button></li>
    </ul>
  </nav>
</template>

<script>
import { computed } from 'vue';
import { useStore } from 'vuex';

export default {
  setup() {
    const store = useStore();
    const isAuthenticated = computed(() => store.state.isAuthenticated);

    const logout = () => {
      store.commit('logout');
      // 登出後返回首頁
      store.$router.push('/');
    };

    return {
      isAuthenticated,
      logout
    };
  }
};
</script>

這裡,我們根據 isAuthenticated 狀態動態顯示登錄和登出按鈕,並在用戶登出時,將其重定向到首頁。

2. 根據 Vuex 狀態跳轉

有時候需要根據 Vuex 的狀態自動跳轉到某個頁面。例如,當用戶已登錄,進入登錄頁面時自動重定向到儀表板頁面。

範例:

1
2
3
4
5
6
7
8
9
10
router.beforeEach((to, from, next) => {
  const isAuthenticated = store.state.isAuthenticated;

  // 如果用戶已登錄並且嘗試訪問登錄頁面,則重定向到儀表板
  if (to.name === 'Login' && isAuthenticated) {
    next({ name: 'Dashboard' });
  } else {
    next();
  }
});

這樣的路由守衛可以避免已登錄用戶再次進入登錄頁面,提供更好的用戶體驗。


5. 總結

Vue RouterVuex 集成,可以幫助你更好地控制路由訪問權限和狀態管理,實現如下功能:

  • 使用 Vuex 管理應用的登錄狀態和用戶信息。
  • 使用 Vue Router 的導航守衛來控制訪問權限,確保用戶只有在登錄後才能訪問某些頁面。
  • 根據 Vuex 狀態動態更新 UI 和進行路由跳轉。
  • 使用 Vuex 和 Vue Router 組合實現更好的用戶登錄和登出體驗。

這種結合方式在處理大型應用時尤為有效,讓開發過程更加簡潔、有條理。

本文章以 CC BY 4.0 授權