因为是在vue源码的基础上进行修改,所以,就没有复制代码在文章上,采取的是截图对比源码和我修改的代码片段。要麻烦你们自己手敲了。
场景:在费用配置列表中,点击每一项的配置,都会在页面容器内部打开一个新页面,所以新页面的路径一样,根据传的参数不同,面包屑和标签页标题动态改变
http://localhost/feeManage/feeConfigDetail?id=4&metaTitle=3253的费用配置
http://localhost/feeManage/feeConfigDetail?id=1&metaTitle=eww的费用配置
// 方法1
this.$router.push({
path: '/feeManage/feeConfig/feeConfigDetail',
query: {
id: row.id,},
})
// 方法2
点击跳转
若依vue前端能跳转到新页面路由的方法,我暂且知道这三种形式:
缺点:因为路由暴露在外面,会发生被误删或者修改错误的情况,造成严重缺陷。
优点:不用写路由配置的代码,可以直接进行路由跳转了。
同时还要注意,这是详细页面,不应该在左侧菜单栏出现,所以要隐藏
若依字典管理的动态路由配置(如果是想实现像若依字典这样的路由跳转效果,就可以直接参考若依的源码去做:
如果需要权限,需要自己写权限标识(很麻烦,,对接很累)
先是后端写上。。。
然后前端。。。
实现三级标题的路由怎么写?
{
path: '/feeManage',
component: Layout, // 一级这个component: Layout必填,除非是不需要在页面容器里打开的页面
hidden: true, // false:显示在侧边栏菜单
redirect: 'noRedirect', // noRedirect:面包屑不可点击,不写这个,父级标题样式就和首页一样,黑字可点击跳转
meta: { title: '费用管理'}, // 一级标题,写了才能显示在面包屑上
children: [
{
path: '',
component:{ render: (e) => e("router-view") }, // 如果你的'feeConfig'路径已经在系统菜单中设置过了,这里的path和component就写得和我一样就行,直接跳转三级路由
hidden: true, // false:显示在侧边栏菜单
redirect: 'noRedirect', // noRedirect:面包屑不可点击,不写这个,父级标题样式就和首页一样,黑字可点击跳转
meta: { title: '费用配置'}, // 二级标题,写了才能显示在面包屑上
// 如果你不需要二级的父级标题,那你就直接把第二个children的内容写在第一个children就行
children: [
{
path: 'feeConfig/feeConfigDetail',
component: () => import('@/views/feeManage/feeConfigDetail/index'),
name: 'feeConfigDetail',
meta: { title: '费用配置', activeMenu: '/feeManage/feeConfig' } // meta.title:三级标题,meta.activeMenu:侧边栏父级菜单高亮
}
]
}
]
}
也可以这样写(这样写是建立在之前写的跳转路径不规范,如果不想改代码那么多,只能自己在路由这里改,就不用动业务代码里的跳转路径,当然我强迫症,我最后都改了)
{
path: '',
component: Layout,
hidden: true,
redirect: 'noRedirect',
meta: { title: '运营中心' },
children: [
{
path: '/overseas-collocation',
component:{ render: (e) => e("router-view") }, // 如果你的'merchant'路径已经在系统菜单中设置过了,这里的path和component就写得和我一样就行,直接跳转三级路由
hidden: true, // false:显示在侧边栏菜单
redirect: 'noRedirect', // noRedirect:面包屑不可点击,不写这个,父级标题样式就和首页一样,黑字可点击跳转
meta: { title: '海外拼柜'}, // 二级标题,写了才能显示在面包屑上
// 如果你不需要二级的父级标题,那你就直接把第二个children的内容写在第一个children就行
children: [
{
path: 'detail/:id(\\d+)',
component: () => import('@/views/operation-center/overseas-collocation/collocation-detail'),
name: 'overseasCollocationDetail',
meta: { title: '拼柜详情', activeMenu: '/operation-center/overseas-collocation/overseas-collocation' }
}
]
}
]
}
查看
改后
配置完路由后,就要讲,如何动态设置路由path不同参数 在页面容器里打开新页面,面包屑和标签页标题根据参数动态改变
使用1方法创建好路由后,然后用$router.push设置传的参数,我们使用metaTitle来当页面标题
this.$router.push({
path: '/feeManage/feeConfigDetail',
query: {
id: row.id,
metaTitle: row.chargeName + '的费用配置'
},
})
如果你只做到了这里,你就会发现,它确实跳转页面了,但是它是同一个页面进行了不同参数的刷新,然后页面的标题也没有动态改变,而是你之前菜单配置时写的标题,如图:
下面就需要改改若依的源码了:
1、先改面包屑
2、在页面容器中,打开新的标签页,改标签页标题(把要修改文件和修改内容框出来,有个明显的对比,知道改哪里)
也是写完上面的内容以后,才发现有bug,路径一样,参数不一样的标签,去单击的时候,没有刷新内容,而是保留第一次点击的标签的页面。。。如图
原因:若依vue前端源码中用的
在自己的跳转页面vue中监听路由参数:
ps: 找到更好的写法就又补充了一下,所以截图上有些不统一,记得看字看描述哈!
ruoyi 3.8.3
{{item.metaTitle ? item.metaTitle : item.meta.title }}
{{ item.meta.title }}
const state = {
visitedViews: [],
cachedViews: []
}
const mutations = {
// ADD_VISITED_VIEW: (state, view) => {
// if (state.visitedViews.some(v => v.path === view.path)) return
// state.visitedViews.push(
// Object.assign({}, view, {
// title: view.meta.title || 'no-name'
// })
// )
// },
ADD_VISITED_VIEW: (state, view) => {
if (state.visitedViews.some(v => v.path === view.path)) {
// 路径一样,因为参数不同,打开新的页面
if(view.query && view.query.metaTitle) {
let list = state.visitedViews.filter(v => v.query && v.query.metaTitle && v.query.metaTitle == view.query.metaTitle)
if(list.length > 0) {
return
}
} else {
return
}
}
state.visitedViews.push(
Object.assign({}, view, {
title: view.query && view.query.metaTitle ? view.query.metaTitle:(view.meta.title || 'no-name')
})
)
},
ADD_CACHED_VIEW: (state, view) => {
if (state.cachedViews.includes(view.name)) return
if (view.meta && !view.meta.noCache) {
state.cachedViews.push(view.name)
}
},
DEL_VISITED_VIEW: (state, view) => {
for (const [i, v] of state.visitedViews.entries()) {
if (v.path === view.path) {
state.visitedViews.splice(i, 1)
break
}
}
},
DEL_CACHED_VIEW: (state, view) => {
const index = state.cachedViews.indexOf(view.name)
index > -1 && state.cachedViews.splice(index, 1)
},
DEL_OTHERS_VISITED_VIEWS: (state, view) => {
state.visitedViews = state.visitedViews.filter(v => {
return v.meta.affix || v.path === view.path
})
},
DEL_OTHERS_CACHED_VIEWS: (state, view) => {
const index = state.cachedViews.indexOf(view.name)
if (index > -1) {
state.cachedViews = state.cachedViews.slice(index, index + 1)
} else {
state.cachedViews = []
}
},
DEL_ALL_VISITED_VIEWS: state => {
// keep affix tags
const affixTags = state.visitedViews.filter(tag => tag.meta.affix)
state.visitedViews = affixTags
},
DEL_ALL_CACHED_VIEWS: state => {
state.cachedViews = []
},
UPDATE_VISITED_VIEW: (state, view) => {
for (let v of state.visitedViews) {
if (v.path === view.path) {
v = Object.assign(v, view)
break
}
}
},
DEL_RIGHT_VIEWS: (state, view) => {
const index = state.visitedViews.findIndex(v => v.path === view.path)
if (index === -1) {
return
}
state.visitedViews = state.visitedViews.filter((item, idx) => {
if (idx <= index || (item.meta && item.meta.affix)) {
return true
}
const i = state.cachedViews.indexOf(item.name)
if (i > -1) {
state.cachedViews.splice(i, 1)
}
return false
})
},
DEL_LEFT_VIEWS: (state, view) => {
const index = state.visitedViews.findIndex(v => v.path === view.path)
if (index === -1) {
return
}
state.visitedViews = state.visitedViews.filter((item, idx) => {
if (idx >= index || (item.meta && item.meta.affix)) {
return true
}
const i = state.cachedViews.indexOf(item.name)
if (i > -1) {
state.cachedViews.splice(i, 1)
}
return false
})
}
}
const actions = {
addView({ dispatch }, view) {
dispatch('addVisitedView', view)
dispatch('addCachedView', view)
},
addVisitedView({ commit }, view) {
commit('ADD_VISITED_VIEW', view)
},
addCachedView({ commit }, view) {
commit('ADD_CACHED_VIEW', view)
},
delView({ dispatch, state }, view) {
return new Promise(resolve => {
dispatch('delVisitedView', view)
dispatch('delCachedView', view)
resolve({
visitedViews: [...state.visitedViews],
cachedViews: [...state.cachedViews]
})
})
},
delVisitedView({ commit, state }, view) {
return new Promise(resolve => {
commit('DEL_VISITED_VIEW', view)
resolve([...state.visitedViews])
})
},
delCachedView({ commit, state }, view) {
return new Promise(resolve => {
commit('DEL_CACHED_VIEW', view)
resolve([...state.cachedViews])
})
},
delOthersViews({ dispatch, state }, view) {
return new Promise(resolve => {
dispatch('delOthersVisitedViews', view)
dispatch('delOthersCachedViews', view)
resolve({
visitedViews: [...state.visitedViews],
cachedViews: [...state.cachedViews]
})
})
},
delOthersVisitedViews({ commit, state }, view) {
return new Promise(resolve => {
commit('DEL_OTHERS_VISITED_VIEWS', view)
resolve([...state.visitedViews])
})
},
delOthersCachedViews({ commit, state }, view) {
return new Promise(resolve => {
commit('DEL_OTHERS_CACHED_VIEWS', view)
resolve([...state.cachedViews])
})
},
delAllViews({ dispatch, state }, view) {
return new Promise(resolve => {
dispatch('delAllVisitedViews', view)
dispatch('delAllCachedViews', view)
resolve({
visitedViews: [...state.visitedViews],
cachedViews: [...state.cachedViews]
})
})
},
delAllVisitedViews({ commit, state }) {
return new Promise(resolve => {
commit('DEL_ALL_VISITED_VIEWS')
resolve([...state.visitedViews])
})
},
delAllCachedViews({ commit, state }) {
return new Promise(resolve => {
commit('DEL_ALL_CACHED_VIEWS')
resolve([...state.cachedViews])
})
},
updateVisitedView({ commit }, view) {
commit('UPDATE_VISITED_VIEW', view)
},
delRightTags({ commit }, view) {
return new Promise(resolve => {
commit('DEL_RIGHT_VIEWS', view)
resolve([...state.visitedViews])
})
},
delLeftTags({ commit }, view) {
return new Promise(resolve => {
commit('DEL_LEFT_VIEWS', view)
resolve([...state.visitedViews])
})
},
}
export default {
namespaced: true,
state,
mutations,
actions
}