diff --git a/src/router/avue-router.js b/src/router/avue-router.js index 039861ea4db85e2469dbc66923ec88f45e58fa1d..94271a066dbcdf9023632d4740fe7618c7da0e9e 100644 --- a/src/router/avue-router.js +++ b/src/router/avue-router.js @@ -1,166 +1,206 @@ - let RouterPlugin = function () { - this.$router = null; - this.$store = null; + this.$router = null; + this.$store = null; }; RouterPlugin.install = function (vue, router, store, i18n) { - this.$router = router; - this.$store = store; - this.$vue = new vue({ i18n }); - function isURL(s) { - return /^http[s]?:\/\/.*/.test(s) - } - function objToform(obj) { - let result = []; - Object.keys(obj).forEach(ele => { - result.push(`${ele}=${obj[ele]}`); - }) - return result.join('&'); - } - this.$router.$avueRouter = { - //全局配置 - $website: this.$store.getters.website, - routerList: [], - group: '', - meta: {}, - safe: this, - // 设置标题 - setTitle: (title) => { - const defaultTitle = this.$vue.$t('title'); - title = title ? `${title}-${defaultTitle}` : defaultTitle; - document.title = title; - }, - closeTag: (value) => { - let tag = value || this.$store.getters.tag; - if (typeof value === 'string') { - tag = this.$store.getters.tagList.filter(ele => ele.value === value)[0] - } - this.$store.commit('DEL_TAG', tag) - }, - generateTitle: (title, key) => { - if (!key) return title; - const hasKey = this.$vue.$te('route.' + key) - if (hasKey) { - // $t :this method from vue-i18n, inject in @/lang/index.js - const translatedTitle = this.$vue.$t('route.' + key) + this.$router = router; + this.$store = store; + this.$vue = new vue({i18n}); - return translatedTitle - } - return title - }, - //处理路由 - getPath: function (params) { - let { src } = params; - let result = src || '/'; - if (src.includes("http") || src.includes("https")) { - result = `/myiframe/urlPath?${objToform(params)}`; - } - return result; - }, - //正则处理路由 - vaildPath: function (list, path) { - let result = false; - list.forEach(ele => { - if (new RegExp("^" + ele + ".*", "g").test(path)) { - result = true - } + // 这个的作用是 为了检查出网页链接,因为本项目用到了 iframe + function isURL(s) { + if (s.includes('html')) return true; + return /^http[s]?:\/\/.*/.test(s) + } + + // 将参数处理为参数的形式拼接 + function objToform(obj) { + let result = []; + Object.keys(obj).forEach(ele => { + result.push(`${ele}=${obj[ele]}`); + }) + return result.join('&'); + } - }) - return result; - }, - //设置路由值 - getValue: function (route) { - let value = ""; - if (route.query.src) { - value = route.query.src; + this.$router.$avueRouter = { + //全局配置 + $website: this.$store.getters.website, + routerList: [], + group: '', + meta: {}, + safe: this, + // 设置标题 + setTitle: (title) => { + const defaultTitle = this.$vue.$t('title'); + title = title ? `${title}-${defaultTitle}` : defaultTitle; + document.title = title; + }, + closeTag: (value) => { + let tag = value || this.$store.getters.tag; + if (typeof value === 'string') { + tag = this.$store.getters.tagList.filter(ele => ele.value === value)[0] + } + this.$store.commit('DEL_TAG', tag) + }, + generateTitle: (title, key) => { + if (!key) return title; + const hasKey = this.$vue.$te('route.' + key) + if (hasKey) { + // $t :this method from vue-i18n, inject in @/lang/index.js + const translatedTitle = this.$vue.$t('route.' + key) + + return translatedTitle + } + return title + }, + //处理路由 + getPath: function (params) { + let {src} = params; + let result = src || '/'; + if (isURL(src)) { + result = `/myiframe/urlPath?${objToform(params)}`; + } + return result; + }, + //正则处理路由 + vaildPath: function (list, path) { + let result = false; + list.forEach(ele => { + if (new RegExp("^" + ele + ".*", "g").test(path)) { + result = true + } + + }) + return result; + }, + //设置路由值 + getValue: function (route) { + let value = ""; + if (route.query.src) { + value = route.query.src; + } else { + value = route.path; + } + return value; + }, + //动态路由 + // 路由是专门的一个接口获取 + /** + * aMenu: 接受到的动态路由数据 menu的结构外层有父级path 里面有一个childen 记录页面的路由 + * first: 为了区分外界 调用formatRoutes 和 当前文件调用 formatRoutes + */ + formatRoutes: function (aMenu = [], first) { + // console.log('aMenu') + // console.log(aMenu) + const aRouter = [] + // 获取到全局配置中的 props + const propsConfig = this.$website.menu.props; + // 设置 props默认值 作用就是将字段设置成配置的 + const propsDefault = { + label: propsConfig.label || 'name', + path: propsConfig.path || 'path', + icon: propsConfig.icon || 'icon', + children: propsConfig.children || 'children', + meta: propsConfig.meta || 'meta', + } + // 如果没有权限菜单就结束 + if (aMenu.length === 0) return; + // 开始处理menu + for (let i = 0; i < aMenu.length; i++) { + // 取到当前要处理的一项 + const oMenu = aMenu[i]; + // 判断this.routerList中是否已经存在该path,存在就跳出 + if (this.routerList.includes(oMenu[propsDefault.path])) return; + // 这一块的赋值 也就是取到返回的值 + let path = (() => { + if (first) { + // 将 '/index' 替换为 '' + return oMenu[propsDefault.path].replace('/index', '') } else { - value = route.path; + return oMenu[propsDefault.path] } - return value; - }, - //动态路由 - formatRoutes: function (aMenu = [], first) { - const aRouter = [] - const propsConfig = this.$website.menu.props; - const propsDefault = { - label: propsConfig.label || 'name', - path: propsConfig.path || 'path', - icon: propsConfig.icon || 'icon', - children: propsConfig.children || 'children', - meta: propsConfig.meta || 'meta', - } - if (aMenu.length === 0) return; - for (let i = 0; i < aMenu.length; i++) { - const oMenu = aMenu[i]; - if (this.routerList.includes(oMenu[propsDefault.path])) return; - const path = (() => { - if (first) { - return oMenu[propsDefault.path].replace('/index', '') - } else { - return oMenu[propsDefault.path] - } - })(), - //特殊处理组件 - component = 'views' + oMenu.path, - name = oMenu[propsDefault.label], - icon = oMenu[propsDefault.icon], - children = oMenu[propsDefault.children], - meta = oMenu[propsDefault.meta] || {}; - - const isChild = children.length !== 0; - const oRouter = { - path: path, - component(resolve) { - // 判断是否为首路由 - if (first) { - require(['../page/index'], resolve) - return - // 判断是否为多层路由 - } else if (isChild && !first) { - require(['../page/index/layout'], resolve) - return - // 判断是否为最终的页面视图 - } else { - require([`../${component}.vue`], resolve) - } - }, - name: name, - icon: icon, - meta: meta, - redirect: (() => { - if (!isChild && first && !isURL(path)) return `${path}/index` - else return ''; - })(), - // 处理是否为一级路由 - children: !isChild ? (() => { - if (first) { - if (!isURL(path)) oMenu[propsDefault.path] = `${path}/index`; - return [{ - component(resolve) { require([`../${component}.vue`], resolve) }, - icon: icon, - name: name, - meta: meta, - path: 'index' - }] - } - return []; - })() : (() => { - return this.formatRoutes(children, false) - })() - } - aRouter.push(oRouter) + })(), + //特殊处理组件 执行完这个 component 也就是精确到具体的文件了 views文件夹下面就是具体的页面代码 + component = 'views' + oMenu.path, + name = oMenu[propsDefault.label], + icon = oMenu[propsDefault.icon], + children = oMenu[propsDefault.children], + meta = oMenu[propsDefault.meta] || {}; + // meta中 keepalive 的处理 + meta = Object.assign(meta, (function () { + if (meta.keepAlive === true) { + return { + $keepAlive: true } + } + })()); + //是否有子路由 + const isChild = children.length !== 0; + const oRouter = { + path: path, + component(resolve) { + // 判断是否为首路由 if (first) { - if (!this.routerList.includes(aRouter[0][propsDefault.path])) { - this.safe.$router.addRoutes(aRouter) - this.routerList.push(aRouter[0][propsDefault.path]) - } + require(['../page/index'], resolve) + return + // 判断是否为多层路由 + } else if (isChild && !first) { + require(['../page/index/layout'], resolve) + return + // 判断是否为最终的页面视图 } else { - return aRouter + require([`../${component}.vue`], resolve) } - + }, + name: name, + icon: icon, + meta: meta, + redirect: (() => { + // 第一次进来但是没有子路由的 需要添加redirect + if (!isChild && first && !isURL(path)) return `${path}/index` + else return ''; + })(), + // 整理子路由的route 配置 + // 处理是否为一级路由 + children: !isChild ? (() => { + if (first) { + // 这里的isURL判断,因为这个网站有使用 iframe。所以需要判断是否为网页链接 + if (!isURL(path)) oMenu[propsDefault.path] = `${path}/index`; + return [{ + component(resolve) { + require([`../${component}.vue`], resolve) + }, + icon: icon, + name: name, + meta: meta, + path: 'index' + }] + } + return []; + })() : (() => { + /** + * 这里是重点,当有子路由的时候 会再去执行 formatRoutes 方法,然后又会有一个新的 aMenu for循环。 + * 最后返回的是一个数组 aRouter 这个数组就会作为 childen的值被 return + */ + return this.formatRoutes(children, false) + })() + } + aRouter.push(oRouter) + } + // for循环结束 + // 这个first 卡的其实就是首路由 + if (first) { + console.log(aRouter) + if (!this.routerList.includes(aRouter[0][propsDefault.path])) { + this.safe.$router.addRoutes(aRouter) + this.routerList.push(aRouter[0][propsDefault.path]) } + } else { + // 这里返回的是子组件 + return aRouter + } } + } } export default RouterPlugin; diff --git a/src/router/router.js b/src/router/router.js index 023a5162e14184e3f4009ce46460e9ccb797dc52..34eb10c9325bc88fd1b20ce0dfbaa3e7edfbb16c 100644 --- a/src/router/router.js +++ b/src/router/router.js @@ -6,30 +6,43 @@ * isTab是否加入到tag导航 * isAuth是否需要授权 */ -import VueRouter from 'vue-router'; -import PageRouter from './page/' -import ViewsRouter from './views/' -import AvueRouter from './avue-router'; import Vue from 'vue'; -import i18n from '@/lang' // Internationalization -import Store from '../store/'; -let Router = new VueRouter({ - scrollBehavior(to, from, savedPosition) { - if (savedPosition) { - return savedPosition - } else { - if (from.meta.keepAlive) { - from.meta.savedPosition = document.body.scrollTop; - } - return { - x: 0, - y: to.meta.savedPosition || 0 - } - } - }, - routes: [] -}); -AvueRouter.install(Vue, Router, Store, i18n); -Router.$avueRouter.formatRoutes(Store.state.user.menu, true); +import VueRouter from 'vue-router'; +import PageRouter from './page/' // 页面路由 +import ViewsRouter from './views/' // 页面路由 +import AvueRouter from './avue-router'; //封装的路由控制方法 +import i18n from '@/lang' // Internationalization 国际化 多语言 +import Store from '../store/'; // vuex +Vue.use(VueRouter) +//创建路由 +export const createRouter = () => new VueRouter({ + // https://router.vuejs.org/zh/guide/advanced/scroll-behavior.html#%E5%BC%82%E6%AD%A5%E6%BB%9A%E5%8A%A8 + // 这个方法 是控制滚动条 + // 如果 retuen falsy || {} ,则不发生滚动 + scrollBehavior (to, from, savedPosition) { + // savedPosition 这个参数当且仅当导航 (通过浏览器的 前进/后退 按钮触发) 时才可用 效果和 router.go() 或 router.back() + if (savedPosition) { + // 返回savedPosition 其实就是 当用户点击 返回的话,保持之前游览的高度 + return savedPosition + } else { + if (from.meta.keepAlive) { + from.meta.savedPosition = document.body.scrollTop + } + return { + x: 0, + y: to.meta.savedPosition || 0 + } + } + }, + routes: [...PageRouter, ...ViewsRouter] +}) +const Router = createRouter() // 获得 route 实例 +AvueRouter.install(Vue, Router, Store, i18n); // 初始化和注册 AvueRouter +Router.$avueRouter.formatRoutes(Store.state.user.menuAll, true); // 动态路由核心方法 Router.addRoutes([...PageRouter, ...ViewsRouter]); -export default Router; \ No newline at end of file +export function resetRouter () { // 重置路由 比如用于身份验证失败,需要重新登录时 先清空当前的路有权限 + const newRouter = createRouter() + Router.matcher = newRouter.matcher // reset router + AvueRouter.install(Vue, Router, Store, i18n); +} +export default Router