Vuex优雅解决地Tabs标签页与菜单路由的一些事一些请

335 阅读2分钟

背景

困扰了我许久,如何优雅地完成Tabs标签页与菜单路由的通信:

  1. 切换菜单生成对应的tabs页
  2. tabs页丝滑切换路由
  3. 页面名称动态切换路由名称 过去我是用eventBussessionStorage和监听$route协同完成的,我利用eventBus的事件监听$on和事件触发$emit来完成通信和参数传输,从而实现子页面路由名称的改变;监听$route,利用sessionStorage实现菜单操作和Tabs标签页的数据通信,需要反复触发sessionStorage的存值和取值操作。

运用Vuex的优势

虽然都会多次触发sessionStorage的存值操作,但只是作为备份数据,防止页面刷新,Tabs栏数据被初始化。其余的数据操作都放在了vuex中完成。

设计实现思维图

由于暂时不存在异步数据操作,所以我这边只是使用了stategettersmutations完成整个流程。

  1. state: 记录当前菜单操作的数据;
  2. getters:针对页面显示需要,对数据进行相应操作,再返回数据给页面;
  3. mutations:设计了四个函数分别是记录菜单操作数据、获取菜单缓存数据、设置当前菜单信息和删除tab信息。 image.png

代码来了

话不多说,来,直接上马!思路马上就上来了!

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

  1. 使用了模块化modules设计,建议开启命名空间namespaced: true
  2. 模块化设计下,调用Vuex的各个对象时,建议使用mapStatemapGettersmapMutationsmapActions,路由方式指向相应模块的相应方法;

感觉

小媛子初次写分享文章,文字笨拙,请各位多多谅解~