【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
}
]
});
在这个示例中,我们创建了一个基本的路由配置文件,并定义了三个路由:Home
、About
和 Contact
。
创建基础组件
接下来,创建对应的页面组件:
// 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 中的 isLoggedIn
和 userRole
状态,并通过 mapActions
获取 logout
方法。我们还添加了一个 isAdmin
计算属性,用于检查当前用户是否是管理员。导航栏中只有管理员才能看到 Admin
菜单项,并且在右上角展示用户的登录状态和退出按钮。
完整项目结构
经过上述步骤,我们已经构建了一个包含以下功能的单页面应用:
- 使用 Element UI 和 Vue Router 创建导航栏和路由。
- 使用 Vuex 管理用户登录状态和权限信息。
- 通过路由守卫实现权限管理和路由访问控制。
项目结构如下:
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 的其他进阶功能,敬请期待!希望这篇文章对你有所帮助,祝你在前端开发的道路上越走越远!