背景
困扰了我许久,如何优雅地完成Tabs
标签页与菜单路由的通信:
- 切换菜单生成对应的tabs页
tabs
页丝滑切换路由- 页面名称动态切换路由名称
过去我是用
eventBus
、sessionStorage
和监听$route
协同完成的,我利用eventBus
的事件监听$on
和事件触发$emit
来完成通信和参数传输,从而实现子页面路由名称的改变;监听$route
,利用sessionStorage
实现菜单操作和Tabs
标签页的数据通信,需要反复触发sessionStorage
的存值和取值操作。
运用Vuex的优势
虽然都会多次触发sessionStorage
的存值操作,但只是作为备份数据,防止页面刷新,Tabs栏数据被初始化。其余的数据操作都放在了vuex
中完成。
设计实现思维图
由于暂时不存在异步数据操作,所以我这边只是使用了state
、getters
、mutations
完成整个流程。
- state: 记录当前菜单操作的数据;
- getters:针对页面显示需要,对数据进行相应操作,再返回数据给页面;
- mutations:设计了四个函数分别是记录菜单操作数据、获取菜单缓存数据、设置当前菜单信息和删除tab信息。
代码来了
话不多说,来,直接上马!思路马上就上来了!
import router from '@/router'
function sessionStorageSave (type, data) {
sessionStorage.setItem(type, JSON.stringify(data))
}
const state = {
currentMenu: {},
tabBarData: [] // tab栏缓存
}
const getters = {
// 标记好需要选择高亮的tab块
currentTabBar: state => {
return state.tabBarData.map(i => {
i.chosed = false
if (i.id === state.currentMenu.id) {
i.chosed = true
}
return i
})
},
// 直接返回当前页面的路由名称
currentMenuName: state => state.currentMenu.label
}
const mutations = {
// 设置当前tab栏的菜单,并备份在sessionStorage
TAB_BAR_SAVE (state, data) {
const hadTab = state.tabBarData.find(i => data.id === i.id)
!hadTab && state.tabBarData.push(data)
sessionStorageSave('tabBarData', state.tabBarData)
},
// 页面刷新后,在sessionStorage拿取备份数据,避免tab栏数据被初始化
TAB_BAR_BACKUP_SET (state, data) {
let currentMenu = JSON.parse(sessionStorage.getItem('currentMenu')) || {}
let tabBarData = JSON.parse(sessionStorage.getItem('tabBarData')) || []
state.currentMenu = currentMenu
if (tabBarData && tabBarData.length > 0) {
state.tabBarData = tabBarData
}
},
// 设置当前页面路由信息,并备份在sessionStorage
MENU_SET (state, data) {
state.currentMenu = data
sessionStorageSave('currentMenu', state.currentMenu)
if (router.app._route.path !== data.uri) {
router.push({
path: data.uri
})
}
},
// 删除tab栏的某个菜单,若tab栏已无菜单数据,默认跳转到首页。
TAB_BAR_REMOVE (state, data) {
state.tabBarData = state.tabBarData.filter(i => i.id !== data.id)
sessionStorageSave('tabBarData', state.tabBarData)
let idx = state.tabBarData.length - 1
if (idx === -1 ) {
router.push({
path: '/main/home'
})
mutations.MENU_SET(state, {
id: '1',
label: '首页',
uri: '/main/home'
})
}
if (router.app._route.path === data.uri) {
router.push({
path: state.tabBarData[idx].uri
})
mutations.MENU_SET(state, state.tabBarData[idx])
}
}
}
export default {
namespaced: true,
state,
getters,
mutations
}
补充说明
vuex
操作的一些小tips
:
- 使用了模块化
modules
设计,建议开启命名空间namespaced: true
; - 模块化设计下,调用Vuex的各个对象时,建议使用
mapState
、mapGetters
、mapMutations
、mapActions
,路由方式指向相应模块的相应方法;
感觉
小媛子初次写分享文章,文字笨拙,请各位多多谅解~