vuex+element 从后台获取数据写导航栏-菜单权限

主要用到 vuexrouter.beforeEachrouter.addRoutes()。vuex 的使用方法可以看我的另一篇博客:vue笔记(四)vuex。

顺便安利一个 在线视频转gif图。

因为第一次用到 router.addRoutes(),在做这个需求的时候遇到了很多问题,这里给大家几个链接,如果碰到了可以点击查看:
1. import 加载组件失败: import() 动态加载component组件失败 ;

2. 路由显示结果正确,但是页面总是跳转到 404 页面: vue 路由权限 页面刷新时报404问题;

3. 每次进入页面时,总是报 name 重复的警告:掘金上的 “luichooy”发表的 vue-router之addRoutes使用遇到的坑,这篇文章对 addRoutes 如何产生这个问题解释挺详细的,但是代码不够详细,我是参考了“学如逆水,不进则退”写的 解决addRoutes后重新登录路由重复警告问题 解决的。


使用vuex 写导航栏

在写静态导航栏时通常会新建一个文件作为组件,数据则是由 this.$router.options.routes 获取。现在我们的路由信息不是从 router 中获取到的,而是从后台获取的,我们暂时先把获取到的这个数据 命名为 menuList,存放在 vuex 中的 state 中。具体代码如下:

思路:

  1. 在 state 中定义一个初始变量 menuList: [],在 actions 中处理请求数据,在 mutations 中将请求到的数据赋值给 state 中的 menuList。
  2. 在组件中获取 state 中处理好的数据。使用 mapGetters
  3. 由于刷新地址,vuex 中的数据会恢复成初始值,使用 router.beforeEach 进行监听,若地址刷新,重新请求数据,使用 $store.dispatch()

1. 登录成功后,发起菜单请求

login(){let userInfo = {token: "ERRR",userCode: "admin",userAccount: "管理员"}sessionStorage.setItem("userInfo", JSON.stringify(userInfo));//dispatch中 userInfo 数据可传可不传,因为刷新的时候,这个数据是拿不到的,总 要从 sessionStorage 中获取this.$store.dispatch("INIT_MENU");this.$router.replace("/")
}

2. 在 store 文件夹下新建 index.js、actions.js、mutations.js、state.js、getters.js。

后台返回数据:(还有一些其他的 id 字段,咱也用不到,这里就不贴了,这个是个大家做一个参考)

{code: "0000",msg: "处理成功",router: [{            path: '/dealCenter',name: 'dealCenter',component: "MyLayout",meta:{  title: "处理中心", hidden: false },children: []},          {path: '/myWorkbench',name: 'myWorkbench',component: "MyLayout",meta:{ title: "我的工作台", hidden: false },children: [{path: "workbenchOne",name: "workbench_one",meta: { title: "工作台一" },component: "/myWorkbench/workbenchOne"},{path: "workbenchTwo",name: "workbench_two",meta: { title: "工作台二" },component: "/myWorkbench/workbenchTwo"},{path: "workbenchThr",name: "workbench_thr",meta: { title: "工作台三" },component: "/myWorkbench/workbenchThr"}]}]
}

代码:

文件名代码描述
index.js
import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
import actions from './actions'
import mutations from './mutations'
import getters from './getters'
Vue.use(Vuex);
export default new Vuex.Store({state, mutations,actions,getters
})
在 index.js 中引入 actions.js、state.js、mutations.js、getters等文件。
state.js
let state = {menuList: []}
export default state;
给 menuList 定义一个初始值。
actions.js
import {menu} from "@/components/commonJs/dealMenuData.js"
"INIT_MENU": ( {commit} ) => {//调用获取菜单的接口,将获取到的值赋值给 routerArr。axios().then( res => {if( res.code === "0000"){commit("GET_MENU", menu(res.router))} else {commit("GET_MENU", []);}}   
})
export default actions;
这里的 menu() 是处理从接口中获取到的数据的方法,将数据转换成 routes 路由格式。
mutations.js
let mutations = {"GET_MENU"(state, paylod){state.menuList = paylod;}
}
export default mutations;
将在 actions.js 中处理好的数据赋值给 state 中的 menuList。
getters.js
let getters = {menuList: (state)=>{return state.menuList;}
}
export default getters;
这里要注意,有else返回 [] 的时候和没有else的区别

3. 处理从后台获取的数据,我在 components 下面新建了一个 commonJs 文件夹,commonJs 下面是 dealMenuData.js 。

这里根据你自己定义的 routes 路由格式进行改写。要注意的是:404页面要在 router.addRoutes() 中拼接,具体原因在 步骤5 中会提到。

import Vue from 'vue'
import MyLayout from "@/components/MyLayout"
import NotFound from '@/components/404'
import router from "@/router"
import {createRouter} from "@/router"function _import(str) { // views文件夹下的Home组件,传入的格式为 'Home'return function (resolve) {require([`@/views${str}.vue`], resolve);};
}const menu = function (arr) { let result = [];//将数据进行处理if(arr.length!=0){for( let i=0; i<arr.length; i++){if( arr[i].children.length == 0 ){ //只有一个子菜单let oneSonArr = {path: "list",name: arr[i].name,meta: arr[i].meta,component: _import(arr[i].path +"/list")}Vue.set(arr[i].children, 0, oneSonArr);} else { //有多个子菜单for(let j=0; j<arr[i].children.length; j++){let sonArrs = {};sonArrs = Object.assign({}, sonArrs, {path: arr[i].children[j].path,name: arr[i].children[j].name,meta: arr[i].children[j].meta,component: _import(arr[i].children[j].component)});Vue.set(arr[i].children, j, sonArrs);  }}result.push({path: arr[i].path,name: arr[i].name,component:  MyLayout,redirect: arr[i].children.length == 1 ? arr[i].path+"/list" : arr[i].path +"/"+ arr[i].children[0].path,meta: arr[i].meta,children: arr[i].children})}}result.push({ path: "*",name: "notFound",meta: { hidden: true },component: NotFound})console.log("在处理函数dealMenuData.js中", router)router.matcher = createRouter().matcher; //清空addRoutes中之前存下的路由信息router.addRoutes(result)return result;
}export {menu};

这一部分可以看一下“前端大虾”的【VUE管理菜单权限】使用router.addRoutes。


4. 导航栏组件中使用:

<template><div>{{menuList}}</div>
</template><script>import { mapGetters } from "vuex";export default {computed: mapGetters(["menuList"])}
</script>

5. 在 router/index.js 中解决页面刷新 menuList 数据被清空的问题:

这里需要注意一下:404 不能写到路由,要在 addroutes 里进行拼接404这个路由。原因是在路由中写 404 ,刷新时因为要调用菜单接口,当前路由下的页面还没有被加载进来,先读取到了写在 router 中的路由,所以会先找到 404页。

import Vue from 'vue'
import VueRouter from 'vue-router'import MyLayout from '@/components/MyLayout'
import Login from '@/components/login/login.vue'
import notFound from '@/components/404'import Store from "@/store"
Vue.use(VueRouter)const routes = [{path: '/',name: 'Home',meta: { hidden: true },redirect: "/dealCenter"},{path: '/login',name: 'login',meta: { hidden: true },component: Login}
]// const router = new VueRouter({
//   mode: 'history',
//   base: process.env.BASE_URL,
//   routes
// })const createRouter  = () => new VueRouter({mode: 'hash',base: process.env.BASE_URL, //根routes
});
const router = createRouter();
export { createRouter };//重复点击导航栏报错
const routerPush = VueRouter.prototype.push;
VueRouter.prototype.push = function (location) {return routerPush.call(this, location).catch(error => error)
}router.beforeEach((to,from,next) => { //全局前置守卫//to: 将要进入目标的路由对象//form: 即将离开的目标路由对象//执行跳转的下一步钩子if(!to.name && !from.name){ Store.dispatch("INIT_MENU") } //刷新时,to.name和from.name都为nullif(!sessionStorage.getItem("userInfo")){ //判断是否存在session值,若不存在表示没有登录if(to.name != "login"){ //判断当前页面是不是登录页next({name:"login"})} else {next();}} else {next();}
})export default router

在router中写404页面后,刷新时的状况如下图:
在这里插入图片描述
用慢速将情景还原一下”:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/362557.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

P3393 逃离僵尸岛 最短路dijkstra

题目描述 小a住的国家被僵尸侵略了&#xff01;小a打算逃离到该国唯一的国际空港逃出这个国家。 该国有N个城市&#xff0c;城市之间有道路相连。一共有M条双向道路。保证没有自环和重边。 K个城市已经被僵尸控制了&#xff0c;如果贸然闯入就会被感染TAT...所以不能进入。由其…

JavaFX技巧7:使用CSS颜色常量/派生颜色

在使用FlexCalendarFX时&#xff0c;我不得不定义一组颜色以可视化不同颜色的不同日历的控件。 每个日历不仅提供一种颜色&#xff0c;还提供几种&#xff1a;用于取消选择/选定/悬停状态的背景和文本颜色。 颜色曾在多个地方使用过&#xff0c;但为了简洁起见&#xff0c;我仅…

import() 动态加载component组件失败

在写 vueelement 从后台获取数据写导航栏 时&#xff0c;当我加载动态路由&#xff0c;import() 总是失败。 假设 path: “/views/Home.vue”&#xff0c;name: “Home”。 一、使用 import() 语法加载组件 参考&#xff1a;“Cookysurongbin”的 解决vue动态路由异步加载im…

进入登录页时,用户名输入框自动聚焦、按enter键让密码框聚焦,完整输入信息后登录

让element-ui的输入框聚焦的4种方式 思路&#xff1a;&#xff08;可以跳过这一步看完整代码——完整代码&#xff09; 1. 进入页面时&#xff0c;用户名输入框就要获取焦点&#xff0c;使用 自定义指令 聚焦更方便。当然也可以用 ref 在 mounted() 钩子函数中让输入框聚焦。 …

vue-cli安装步骤

vue-cli脚手架模板是基于node下的npm来完成安装的所以首先需要安装node 条件&#xff1a; node在4.以上&#xff0c;npm在3以上 安装 指令&#xff1a; 1、 npm install -g vue-cli在全局下安装vue-cli # 安装 vue-cli npm install -g vue-cli# 初始化 webpack 项目 vue in…

使用Java编写简单的老虎机游戏

无论游戏多么简单或复杂 &#xff0c;Java都能胜任&#xff01; 在这篇文章中&#xff0c;让我们看一下Java编程的初学者如何制作一个简单而功能齐全的老虎机。 老虎机已经存在很长时间了&#xff0c;但是它的娱乐价值似乎并没有减弱。 InterCasino是第一个在1996年向世界提供…

html笔记(二)html4+css2.0(元素类型、css精灵、宽度自适应、BFC、浏览器相关概述、css统筹)

大标题小节一、元素类型1. 元素分类2. 置换和非置换元素3. 元素类型转换二、css精灵三、宽高自适应1. 宽度自适应2. 高度自适应3. 最小高度自适应4. 高度塌陷及解决办法5. 元素的高度自适应屏幕的高度四、BEC概念应用1. 常见定位方案2. 触发BFC3. BFC特性及应用4. BFC概念五、浏…

25.C# 异步调用Web服务

1.创建Web服务 1.1VS新建ASP.Net空Web应用程序 1.2添加Web服务新建项 1.3添加GetWeather方法和相关类 using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Services; using System.EnterpriseServices;namespace WebServ…

css中单位的使用

css中许多的属性都需要添加长度&#xff0c;而长度一般由数字和单位构成&#xff0c;如1px,1.5em,2vh&#xff1b;也可以省略单位&#xff0c;如line-height:1.5,表示行高为字体大小的1.5倍&#xff1b; 长度单位一般也分为相对长度和绝对长度。 &#xff08;一&#xff09;绝…

OSGi:进入微服务架构的门户

在构建可扩展&#xff0c;可靠的分布式系统的背景下&#xff0c;“模块化”和“微服务体系结构”这两个术语如今经常出现。 众所周知&#xff0c;Java平台本身在模块化方面很弱&#xff08; Java 9将通过交付Jigsaw项目来解决这一问题&#xff09;&#xff0c;从而为OSGi和JBos…

html笔记(五)2D、3D、3D动画

大标题小节一、2D1. css3 渐变的语法及应用2. 动画过渡&#xff1a;transition3. 2D转换属性&#xff1a;transform二、3D1. 3D转换2. 3D视距3. 3D翻转方法4. 3D位置移动5. 3D缩放三、3D动画1. keyframes2. 动画属性animation一、2D 1. css3 渐变的语法及应用&#xff1b; &a…

基于上下文的访问控制

拓扑图 配置步骤 1配置端口ip地址&#xff0c;并检测连通性 服务器 ping pc端 服务器 telnet R3 2配置命令 R3(config)# ip access-list extended go R3(config-ext-nacl)# deny ip any any //此ACL目的是隔绝外网流量 R3(config-ext-nacl)# exit R3(config)# interface s0…

使用Gradle将JAR工件发布到Artifactory

因此&#xff0c;我浪费了一两天&#xff08;投资&#xff09;只是为了了解如何使用Gradle将JAR发布到本地运行的Artifactory服务器。 我使用Gradle Artifactory插件进行发布。 我迷失了无穷循环&#xff0c;包括各种版本的各种插件和执行各种任务。 是的&#xff0c;我之前阅读…

Combox使用的一些技巧

这些天做一个小型的CMS&#xff0c;也就几张表&#xff0c;用WCFLINQ2SQLSilverlight这种方式开发的&#xff0c;对最常用的控件如DataGrid,DataForm以及Toolkit里其它一些控件的用法有了一定的了解&#xff0c;同时参照JV9的教程&#xff0c;把Silverlight里的验证机制仔细的学…

HTML+css实现的效果

一、鼠标划过效果 1. 类似电子书的图书效果2. 绝对定位实用案例 二、锚点的应用 三、css精灵&#xff08;图片整合&#xff09; 用一张图片写出一串电话号码用一张图片写出导航栏的滑动效果 四、后台管理布局 单飞布局双飞布局后台页面管理布局 五、css3部分 在一个div…

[LeetCode] Longest Substring Without Repeating Characters 最长无重复字符的子串 C++实现java实现...

最长无重复字符的子串 Given a string, find the length of the longest substring without repeating characters. Example 1: Input: "abcabcbb" Output: 3 Explanation: The answer is "abc", with the length of 3. Example 2: Input: "bbbbb&qu…

使用自动机的Lucene新的邻近查询

最简单的Apache Lucene查询TermQuery匹配包含指定术语的任何文档&#xff0c;无论该术语出现在每个文档中的何处 。 使用BooleanQuery可以将多个TermQuery组合在一起&#xff0c;并完全控制哪些术语是可选的&#xff08; SHOULD &#xff09;和哪些是必需的&#xff08; MUST &…

关于HTML的面试题-html4/css2篇

1. 什么是HTML&#xff1f;2. 用过什么调试器&#xff08;浏览器&#xff09;&#xff0c;编辑器&#xff1f;3. HTML4.0 和 HTML5.0 的区别&#xff1f;4. 手写 HTML 代码5. 元素类型有哪些&#xff08;display有哪些属性&#xff09;&#xff1f;块元素、行元素和行内块元素的…

Java EE:异步构造和功能

介绍 Java EE具有许多API和构造以支持异步执行。 从可伸缩性和性能的角度来看&#xff0c;这是至关重要的。 让我们假设2个模块相互交互。 当模块A &#xff08;发送方&#xff09;以同步方式向模块B &#xff08;接收方&#xff09;发送消息时&#xff0c;通信将在单个线程的…

用 JA Transmenu 模块做多级弹出菜单

转自http://www.joomlagate.com “弹出菜单”这个说法本来不规范&#xff0c;尽管你我都明白这是什么意思&#xff0c;而实际上我们所理解的那个菜单样式英文说法是“Slide Menu”&#xff08;滑动菜单&#xff09;&#xff0c;如果要用“弹出菜单”就成了“Popup Menu”。当然…