【Element进阶】2、Element UI与Vue Router结合

【Element进阶】Element UI与Vue Router结合


系列文章导航:

【Element进阶】1、深入理解Element UI的国际化
【Element进阶】2、Element UI与Vue Router结合(本文)
【Element进阶】3、Element UI与Vuex结合
【Element进阶】4、Element UI 复杂表单处理
【Element进阶】5、自定义组件与Element UI集成
【Element进阶】6、Element UI 高阶数据展示
【Element进阶】7、Element UI 性能优化
【Element进阶】8、Element UI 最佳实践与案例分析


在现代 Web 应用开发中,单页面应用(SPA)已经成为主流。Vue.js 提供了强大的路由功能,通过 Vue Router 可以轻松地管理应用的导航和视图切换。而 Element UI 提供了丰富的组件库,可以与 Vue Router 无缝结合,快速构建功能强大且美观的单页面应用。本篇文章将详细介绍如何使用 Element UI 和 Vue Router 创建单页面应用,并实现导航守卫与权限管理。

使用Element UI和Vue Router创建单页面应用

基本概念

Vue Router 是 Vue.js 的官方路由管理器,它深度集成了 Vue.js 核心,支持嵌套路由、动态路由、路由守卫等功能。通过结合 Element UI 的导航组件,我们可以轻松地创建一个功能完善的单页面应用。

安装和配置 Vue Router

首先,安装 Vue Router:

npm install vue-router --save

然后,在项目中配置 Vue Router:

// src/router/index.js
import Vue from 'vue';
import Router from 'vue-router';
import Home from '@/components/Home.vue';
import About from '@/components/About.vue';
import Contact from '@/components/Contact.vue';

Vue.use(Router);

export default new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'Home',
      component: Home
    },
    {
      path: '/about',
      name: 'About',
      component: About
    },
    {
      path: '/contact',
      name: 'Contact',
      component: Contact
    }
  ]
});

在这个示例中,我们创建了一个基本的路由配置文件,并定义了三个路由:HomeAboutContact

创建基础组件

接下来,创建对应的页面组件:

// src/components/Home.vue
<template>
  <div>
    <h1>Home</h1>
    <p>Welcome to the home page!</p>
  </div>
</template>

<script>
export default {
  name: 'Home'
};
</script>
// src/components/About.vue
<template>
  <div>
    <h1>About</h1>
    <p>About us page content.</p>
  </div>
</template>

<script>
export default {
  name: 'About'
};
</script>
// src/components/Contact.vue
<template>
  <div>
    <h1>Contact</h1>
    <p>Contact us page content.</p>
  </div>
</template>

<script>
export default {
  name: 'Contact'
};
</script>

配置主应用入口

main.js 中引入和配置 Vue Router:

// src/main.js
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

Vue.config.productionTip = false;

Vue.use(ElementUI);

new Vue({
  router,
  render: h => h(App)
}).$mount('#app');

创建导航栏

最后,使用 Element UI 的 Menu 组件创建导航栏:

// src/App.vue
<template>
  <div id="app">
    <el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect">
      <el-menu-item index="1" route="/"><router-link to="/">Home</router-link></el-menu-item>
      <el-menu-item index="2" route="/about"><router-link to="/about">About</router-link></el-menu-item>
      <el-menu-item index="3" route="/contact"><router-link to="/contact">Contact</router-link></el-menu-item>
    </el-menu>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      activeIndex: '1'
    };
  },
  methods: {
    handleSelect(key, keyPath) {
      this.activeIndex = key;
    }
  }
};
</script>

<style>
.el-menu-demo {
  background-color: #333;
  color: #fff;
}
.el-menu-demo .el-menu-item {
  color: #fff;
}
</style>

在这个示例中,我们创建了一个包含三个导航项的导航栏,并使用 router-link 组件实现路由跳转。通过 router-view 组件,页面内容会根据当前路由自动更新。

导航守卫与权限管理

基本概念

导航守卫是 Vue Router 提供的一种导航钩子,用于在路由跳转前或跳转后执行特定的逻辑。通过导航守卫,我们可以实现权限管理、登录验证、动态标题等功能。

全局导航守卫

全局导航守卫适用于所有路由,可以在路由实例中配置:

// src/router/index.js
import Vue from 'vue';
import Router from 'vue-router';
import Home from '@/components/Home.vue';
import About from '@/components/About.vue';
import Contact from '@/components/Contact.vue';

Vue.use(Router);

const router = new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'Home',
      component: Home
    },
    {
      path: '/about',
      name: 'About',
      component: About,
      meta: { requiresAuth: true }
    },
    {
      path: '/contact',
      name: 'Contact',
      component: Contact
    }
  ]
});

router.beforeEach((to, from, next) => {
  // 检查路由是否需要验证
  if (to.matched.some(record => record.meta.requiresAuth)) {
    // 这里检查用户是否已登录
    if (!isLoggedIn()) {
      next({
        path: '/',
        query: { redirect: to.fullPath }
      });
    } else {
      next();
    }
  } else {
    next();
  }
});

function isLoggedIn() {
  // 这里应该是实际的验证逻辑,例如检查 token 是否存在
  return localStorage.getItem('user-token');
}

export default router;

在这个示例中,我们在 About 路由上添加了 meta: { requiresAuth: true },表示该路由需要认证。通过 router.beforeEach 钩子,我们在每次导航前检查用户是否已登录,如果未登录则重定向到首页。

路由独享的守卫

路由独享守卫是特定于某个路由的导航守卫,可以在路由配置中直接定义:

// src/router/index.js
const routes = [
  {
    path: '/about',
    name: 'About',
    component: About,
    beforeEnter: (to, from, next) => {
      if (!isLoggedIn()) {
        next('/');
      } else {
        next();
      }
    }
  }
];

在这个示例中,我们在 About 路由上添加了 beforeEnter 守卫,执行和全局守卫类似的登录检查逻辑。

组件内的守卫

组件内的守卫是在组件内定义的导航钩子,适用于特定组件的导航检查:

// src/components/About.vue
<template>
  <div>
    <h1>About</h1>
    <p>About us page content.</p>
  </div>
</template>

<script>
export default {
  name: 'About',
  beforeRouteEnter(to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建
    next(vm => {
      if (!vm.isLoggedIn()) {
        next('/');
      } else {
        next();
      }
    });
  },
  methods: {
    isLoggedIn() {
      return localStorage.getItem('user-token');
    }
  }
};
</script>

在这个示例中,我们在组件内定义了 beforeRouteEnter 导航钩子,同样用于登录检查。

权限管理

为了实现更复杂的权限管理,我们可以将用户权限信息存储在 Vuex 中,并在导航守卫中进行验证:

// src/store/index.js
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    user: null
  },
  mutations: {
    setUser(state, user) {
      state.user = user;
    }
  },
  actions: {
    login({ commit }, user) {
      // 模拟登录操作
      localStorage.setItem('user-token', user.token);
      commit('setUser', user);
    },
    logout({ commit }) {
      localStorage.removeItem('user-token');
      commit('setUser', null);
    }
  },
  getters: {
    isLoggedIn: state => !!state.user,
    userRole: state => state.user ? state.user.role : null
  }
});

在这个示例中,我们在 Vuex 中存储了用户信息,并提供了登录和退出操作。getters 用于获取用户的登录状态和角色信息。

路由配置和导航守卫

接下来,我们在路由配置中使用 Vuex 进行权限验证:

// src/router/index.js
import Vue from 'vue';
import Router from 'vue-router';
import store from '@/store';
import Home from '@/components/Home.vue';
import About from '@/components/About.vue';
import Contact from '@/components/Contact.vue';
import Admin from '@/components/Admin.vue';

Vue.use(Router);

const router = new Router({
  mode: 'history',
  routes: [
    {
      path: '/',
      name: 'Home',
      component: Home
    },
    {
      path: '/about',
      name: 'About',
      component: About,
      meta: { requiresAuth: true }
    },
    {
      path: '/contact',
      name: 'Contact',
      component: Contact
    },
    {
      path: '/admin',
      name: 'Admin',
      component: Admin,
      meta: { requiresAuth: true, roles: ['admin'] }
    }
  ]
});

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) {
    if (!store.getters.isLoggedIn) {
      next({
        path: '/',
        query: { redirect: to.fullPath }
      });
    } else if (to.matched.some(record => record.meta.roles)) {
      const userRole = store.getters.userRole;
      if (to.meta.roles.includes(userRole)) {
        next();
      } else {
        next({ path: '/' });
      }
    } else {
      next();
    }
  } else {
    next();
  }
});

export default router;

在这个示例中,我们新增了 Admin 路由,并在其 meta 属性中指定了需要 admin 角色。通过 router.beforeEach 导航守卫,我们首先检查路由是否需要认证,如果需要认证但用户未登录,则重定向到首页。对于需要特定角色的路由,我们进一步检查用户角色是否匹配。

创建 Admin 组件

创建 Admin.vue 组件,用于展示只有管理员可以访问的内容:

// src/components/Admin.vue
<template>
  <div>
    <h1>Admin Page</h1>
    <p>Welcome, administrator!</p>
  </div>
</template>

<script>
export default {
  name: 'Admin'
};
</script>

完整的 App.vue

App.vue 中添加导航栏,并展示用户登录状态和退出按钮:

<template>
  <div id="app">
    <el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect">
      <el-menu-item index="1" route="/"><router-link to="/">Home</router-link></el-menu-item>
      <el-menu-item index="2" route="/about"><router-link to="/about">About</router-link></el-menu-item>
      <el-menu-item index="3" route="/contact"><router-link to="/contact">Contact</router-link></el-menu-item>
      <el-menu-item index="4" route="/admin" v-if="isAdmin"><router-link to="/admin">Admin</router-link></el-menu-item>
    </el-menu>
    <div class="login-status">
      <span v-if="isLoggedIn">Logged in as: {{ userRole }}</span>
      <el-button type="text" @click="logout" v-if="isLoggedIn">Logout</el-button>
    </div>
    <router-view></router-view>
  </div>
</template>

<script>
import { mapGetters,mapActions } from 'vuex';

export default {
  name: 'App',
  data() {
    return {
      activeIndex: '1'
    };
  },
  computed: {
    ...mapGetters(['isLoggedIn', 'userRole']),
    isAdmin() {
      return this.userRole === 'admin';
    }
  },
  methods: {
    ...mapActions(['logout']),
    handleSelect(key, keyPath) {
      this.activeIndex = key;
    }
  }
};
</script>

<style>
.el-menu-demo {
  background-color: #333;
  color: #fff;
}
.el-menu-demo .el-menu-item {
  color: #fff;
}
.login-status {
  float: right;
  padding: 10px;
  color: #fff;
}
</style>

在这个示例中,我们通过 mapGetters 获取 Vuex 中的 isLoggedInuserRole 状态,并通过 mapActions 获取 logout 方法。我们还添加了一个 isAdmin 计算属性,用于检查当前用户是否是管理员。导航栏中只有管理员才能看到 Admin 菜单项,并且在右上角展示用户的登录状态和退出按钮。

完整项目结构

经过上述步骤,我们已经构建了一个包含以下功能的单页面应用:

  1. 使用 Element UI 和 Vue Router 创建导航栏和路由。
  2. 使用 Vuex 管理用户登录状态和权限信息。
  3. 通过路由守卫实现权限管理和路由访问控制。

项目结构如下:

src/
|-- components/
|   |-- Home.vue
|   |-- About.vue
|   |-- Contact.vue
|   |-- Admin.vue
|-- i18n/
|   |-- en.js
|   |-- zh-CN.js
|   |-- messages.js
|-- router/
|   |-- index.js
|-- store/
|   |-- index.js
|-- App.vue
|-- main.js

通过这个项目结构,我们可以清晰地管理组件、路由、国际化和状态管理,使项目更加模块化和易于维护。

结语

通过本章的学习,我们深入了解了如何结合 Element UI 和 Vue Router 创建单页面应用,并实现导航守卫与权限管理。我们探讨了路由配置、全局和局部导航守卫的使用方法,以及如何通过 Vuex 管理用户状态和权限信息。

通过掌握这些技能,我们可以构建更加安全、灵活的单页面应用,提升用户体验和项目的可维护性。

在接下来的章节中,我们将继续深入探讨 Element UI 的其他进阶功能,敬请期待!希望这篇文章对你有所帮助,祝你在前端开发的道路上越走越远!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值