vue动态显示vue route 隐藏主组件组件如何实现

为了账号安全,请及时绑定邮箱和手机
点击这里,将文章分享到自己的动态
权限管理模块中动态加载Vue组件
当前后端分离时,权限问题的处理也和我们传统的处理方式有一点差异。笔者前几天刚好在负责一个项目的权限管理模块,现在权限管理模块已经做完了,我想通过5-6篇文章,来介绍一下项目中遇到的问题以及我的解决方案,希望这个系列能够给小伙伴一些帮助。本系列文章并不是手把手的教程,主要介绍了核心思路并讲解了核心代码,完整的代码小伙伴们可以在GitHub上star并clone下来研究。另外,原本计划把项目跑起来放到网上供小伙伴们查看,但是之前买服务器为了省钱,内存只有512M,两个应用跑不起来(已经有一个在运行),因此小伙伴们只能将就看一下下面的截图了,GitHub上有部署教程,部署到本地也可以查看完整效果。
项目地址:
前面几篇文章,我们已经基本解决了服务端的问题,并封装了前端请求,本文我们主要来聊聊登录以及组件的动态加载。
本文是本系列的第五篇,建议先阅读前面的文章有助于更好的理解本文:
登录状态保存
当用户登录成功之后,需要将当前用户的登录信息保存在本地,方便后面使用。具体实现如下:
登录成功保存数据
在登录操作执行成功之后,通过commit操作将数据提交到store中,核心代码如下:
this.postRequest('/login', {
username: this.loginForm.username,
password: this.loginForm.password
}).then(resp=& {
if (resp && resp.status == 200) {
var data = resp.
_this.$store.commit('login', data.msg);
var path = _this.$route.query.
_this.$router.replace({path: path == '/' || path == undefined ? '/home' : path});
store的核心代码如下:
export default new Vuex.Store({
name: window.localStorage.getItem('user' || '[]') == null ? '未登录' : JSON.parse(window.localStorage.getItem('user' || '[]')).name,
userface: window.localStorage.getItem('user' || '[]') == null ? '' : JSON.parse(window.localStorage.getItem('user' || '[]')).userface
mutations: {
login(state, user){
state.user =
window.localStorage.setItem('user', JSON.stringify(user));
logout(state){
window.localStorage.removeItem('user');
为了减少麻烦,用户登录成功后的数据将被保存在localStorage中(防止用户按F5刷新之后数据丢失),以字符串的形式存入,取的时候再转为json。当用户注销登陆时,将localStorage中的数据清除。
组件动态加载
在权限管理模块中,这算是前端的核心了。
用户在登录成功之后,进入home主页之前,向服务端发送请求,要求获取当前的菜单信息和组件信息,服务端根据当前用户所具备的角色,以及角色所对应的资源,返回一个json字符串,格式如下:
"path": "/home",
"component": "Home",
"name": "员工资料",
"iconCls": "fa fa-user-circle-o",
"children": [
"id": null,
"path": "/emp/basic",
"component": "EmpBasic",
"name": "基本资料",
"iconCls": null,
"children": [],
"keepAlive": false,
"requireAuth": true
"id": null,
"path": "/emp/adv",
"component": "EmpAdv",
"name": "高级资料",
"iconCls": null,
"children": [],
"keepAlive": false,
"requireAuth": true
"keepAlive": false,
"requireAuth": true
前端在拿到这个字符串之后,做两件事:1.将json动态添加到当前路由中;2.将数据保存到store中,然后各页面根据store中的数据来渲染菜单。
核心思路并不难,下面我们来看看实现步骤。
数据请求时机
这个很重要。
可能会有小伙伴说这有何难,登录成功之后请求不就可以了吗?是的,登录成功之后,请求菜单资源是可以的,请求到之后,我们将之保存在store中,以便下一次使用,但是这样又会有另外一个问题,假如用户登录成功之后,点击某一个子页面,进入到子页面中,然后按了一下F5进行刷新,这个时候就GG了,因为F5刷新之后store中的数据就没了,而我们又只在登录成功的时候请求了一次菜单资源,要解决这个问题,有两种思路:1.将菜单资源不要保存到store中,而是保存到localStorage中,这样即使F5刷新之后数据还在;2.直接在每一个页面的mounted方法中,都去加载一次菜单资源。
由于菜单资源是非常敏感的,因此最好不要不要将其保存到本地,故舍弃方案1,但是方案2的工作量有点大,因此我采取办法将之简化,采取的办法就是使用路由中的导航守卫。
路由导航守卫
我的具体实现是这样的,首先在store中创建一个routes数组,这是一个空数组,然后开启路由全局守卫,如下:
router.beforeEach((to, from, next)=& {
if (to.name == 'Login') {
var name = store.state.user.
if (name == '未登录') {
if (to.meta.requireAuth || to.name == null) {
next({path: '/', query: {redirect: to.path}})
initMenu(router, store);
这里的代码很短,我来做一个简单的解释:
1.如果要去的页面是登录页面,这个没啥好说的,直接过。
2.如果不是登录页面的话,我先从store中获取当前的登录状态,如果未登录,则通过路由中meta属性的requireAuth属性判断要去的页面是否需要登录,如果需要登录,则跳回登录页面,同时将要去的页面的path作为参数传给登录页面,以便在登录成功之后跳转到目标页面,如果不需要登录,则直接过(事实上,本项目中只有Login页面不需要登录);如果已经登录了,则先初始化菜单,再跳转。
初始化菜单的操作如下:
export const initMenu = (router, store)=& {
if (store.state.routes.length & 0) {
getRequest("/config/sysmenu").then(resp=& {
if (resp && resp.status == 200) {
var fmtRoutes = formatRoutes(resp.data);
router.addRoutes(fmtRoutes);
store.commit('initMenu', fmtRoutes);
export const formatRoutes = (routes)=& {
let fmRoutes = [];
routes.forEach(router=& {
component,
if (children && children instanceof Array) {
children = formatRoutes(children);
let fmRouter = {
path: path,
component(resolve){
if (component.startsWith("Home")) {
require(['../components/' + component + '.vue'], resolve)
} else if (component.startsWith("Emp")) {
require(['../components/emp/' + component + '.vue'], resolve)
} else if (component.startsWith("Per")) {
require(['../components/personnel/' + component + '.vue'], resolve)
} else if (component.startsWith("Sal")) {
require(['../components/salary/' + component + '.vue'], resolve)
} else if (component.startsWith("Sta")) {
require(['../components/statistics/' + component + '.vue'], resolve)
} else if (component.startsWith("Sys")) {
require(['../components/system/' + component + '.vue'], resolve)
name: name,
iconCls: iconCls,
meta: meta,
children: children
fmRoutes.push(fmRouter);
return fmR
在初始化菜单中,首先判断store中的数据是否存在,如果存在,说明这次跳转是正常的跳转,而不是用户按F5或者直接在地址栏输入某个地址进入的。否则就去加载菜单。拿到菜单之后,首先通过formatRoutes方法将服务器返回的json转为router需要的格式,这里主要是转component,因为服务端返回的component是一个字符串,而router中需要的却是一个组件,因此我们在formatRoutes方法中动态的加载需要的组件即可。数据格式准备成功之后,一方面将数据存到store中,另一方面利用路由中的addRoutes方法将之动态添加到路由中。
最后,在Home页中,从store中获取菜单json,渲染成菜单即可,相关代码可以在Home.vue中查看,不赘述。
OK,如此之后,不同用户登录成功之后就可以看到不同的菜单了。
本文原创发布于慕课网 ,转载请注明出处,谢谢合作
若觉得本文不错,就分享一下吧!
评论加载中...
看过此文的用户,还看了以下文章
正在加载中
JAVA开发工程师
作者相关文章404 Not Found
The requested URL /q/1443 was not found on this server.vue-router无法实现按需加载动态组件,有什么替代方案可以解决这一需求呢? - 知乎有问题,上知乎。知乎作为中文互联网最大的知识分享平台,以「知识连接一切」为愿景,致力于构建一个人人都可以便捷接入的知识分享网络,让人们便捷地与世界分享知识、经验和见解,发现更大的世界。185被浏览<strong class="NumberBoard-itemValue" title="2分享邀请回答3添加评论分享收藏感谢收起404 Not Found
The requested URL /q/9934 was not found on this server.Vue2.0如何实现父组件与子组件之间的事件发射与接收
&&&&&关于vue2.0的事件发射和接收,大家都知道$dispatch和$broadcast在vue2.0已经被弃用了,取而代之的是更加方便快捷的方式,使用事件中心,组件通过它来互相通信,不管组件在哪一个层都可以通过实例化一个空Vue来实现。上案例:
&&&&这是自己写的一个小案例,功能就是点击子组件的加减按钮控制父组件的数量变化。原理就是子组件的加减按钮点击时分发事件,父组件接收事件。
相信html和css的代码大家都没问题,这里不赘述,直接说js部分,首先在项目初始化时先给data添加名为eventHub的空Vue对象,作用是让任何组件都可以调用事件发射和接收的方法。代码如下:
在点击加号按钮时向父组件派发事件:
由于我写的json数据是两层的:
所以两层循环把数据展示在页面上,要精确将某个食物的数量显示必须知道第一大类和这一大类下这个食物的索引值,在这里在html那里先把两个索引传进子组件,在分发事件时再和数量一起打包成对象发射给父组件。
记得子组件要在props里对child,parent进行声明,接着是父组件对发射过来的countFunc进行接收:
到了这个时候将子组件传过来的countFunc里的obj进行console.log(),你会发现父组件已经接收了一个对象:
Object {count: 1, index: 0, parent:
0},也就是当我点击一下苹果的加号按钮时传过来count为1说明数量为1,parent索引为0说明是第一大类,index为0说明是第一大类下的苹果,至此已经实现了父子组件之间的事件发射和接收。
完整代码如下:
&&&&&&如需转载请注明出处:,以便有错误可以及时修改,初涉Vue难免有错漏不足之处,请见谅并且指点,谢谢!!!
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 vue组件的显示隐藏 的文章

 

随机推荐