import {defineStore} from "pinia"; import router from "@/router.js"; import useEventEmitter from "@hooks/useEventEmitter.js"; import commonUtil from "@utility/commonUtil.js"; import tabBarOption from "@/tabBar.js"; export const routerEventEmitter = useEventEmitter(); const tabBar = tabBarOption.map(el => el.pathName) //tabbar页面; /** * @method defaultCurrentPagesFun 默认当前路由 * */ const defaultCurrentPagesFun = () => { let defaultCurrentPages = []; if (tabBar.length) { defaultCurrentPages = [{ pathName: tabBar[0], params: [], cache: true }] } return defaultCurrentPages; } /** * @method isNavigate 判断导航 * @param navigateInfo { String | JSON } 导航信息 * */ const isNavigate = (navigateInfo) => { let isTabBar = false; let isNavStr = false; if (commonUtil.isStr(navigateInfo)) { isNavStr = true; if (tabBar.includes(navigateInfo)) { isTabBar = true; } } else { isNavStr = false; if (tabBar.includes(navigateInfo.pathName)) { isTabBar = true; } } return [isTabBar, isNavStr]; }; const useRouterStore = defineStore('routerStore', { state: () => ({ currentPages: defaultCurrentPagesFun(),//当前已跳转页面列表 historyPages: [] //当前已回退页面列表 }), actions: {//actions是store的方法methods /*** * @method navigateTo 保留当前页面,跳转某个页面,不能跳转跳转到tabBar页面 * @param navigateInfo { String | JSON } 导航信息 navigateInfo = pathName navigateInfo = { pathName:'', 路由名称 success: ()=>{} 路由跳转成功函数 } * */ async navigateTo(navigateInfo) { const [isTabBar, isNavStr] = isNavigate(navigateInfo); if (!isTabBar) { let pathName = isNavStr ? navigateInfo : navigateInfo.pathName; await router.push(pathName); this.update(pathName); if (commonUtil.isFun(navigateInfo.success)) navigateInfo.success(); } }, /** * @method navigateBack 关闭当前页面,返回上一页面或多级页面 * @param backInfo { Number | JSON } 导航信息 返回的页面数,默认1 backInfo={ delta: 1, success: ()=>{} 路由跳转成功函数 } * */ navigateBack(backInfo = 1) { let delta = backInfo; const backPageRouter = this.currentPages[this.currentPages.length - 2]; this.updateCacheStatus(backPageRouter.pathName); //返回一个页面由路由监听处理,主要为了兼容浏览器自带的返回 if (commonUtil.isJson(backInfo)) { delta = backInfo.delta || 1; } if (delta > 1) { router.go(-delta); this.delete(delta); } else { router.back(); } // 返回页面,真实内容的渲染会慢一拍;这里用定时处理 if (commonUtil.isFun(backInfo.success)) { const navigateBackTimeout = setTimeout(() => { backInfo.success(); clearTimeout(navigateBackTimeout); }, 30) } }, /*** * @method switchTabBar 跳转到tabBar页面,并关闭其他所有非tabBar页面 * @param navigateInfo { String | JSON } 导航信息 navigateInfo = pathName navigateInfo = { pathName:'', 路由名称 success: ()=>{} 路由跳转成功函数 } * */ async switchTabBar(navigateInfo) { const [isTabBar, isNavStr] = isNavigate(navigateInfo); if (isTabBar) { let pathName = isNavStr ? navigateInfo : navigateInfo.pathName; await router.replace(pathName); if (commonUtil.isFun(navigateInfo.success)) navigateInfo.success(); this.currentPages = [{ pathName: pathName, params: [], //emit传递的参数集合 cache: true //页面是否缓存 }]; //跳转tabBar页,相当于重新开始路由跳转,需清空已回退页面列表 this.historyPages = []; } }, /*** * @method redirectTo 关闭当前页面,跳转某个页面。但是不允许跳转到tabBar页面 * @param navigateInfo { String | JSON } 导航信息 navigateInfo = pathName navigateInfo = { pathName:'', 路由名称 success: ()=>{} 路由跳转成功函数 } * */ async redirectTo(navigateInfo) { const [isTabBar, isNavStr] = isNavigate(navigateInfo); if (!isTabBar) { let pathName = isNavStr ? navigateInfo : navigateInfo.pathName; await router.replace(pathName); if (commonUtil.isFun(navigateInfo.success)) navigateInfo.success(); this.deleteHistory(pathName); } }, /** * @method emit 触发特定事件,并依次调用与该事件关联的所有监听器函数 * @param eventName {String} 事件名 * @param par {Any} 传给监听事件的参数 * */ emit(eventName, par) { const currentPage = this.currentPages[this.currentPages.length - 1]; const paramIndex = currentPage.params?.findIndex(el => Reflect.ownKeys(el)[0] == eventName) if (paramIndex > -1) { currentPage.params[paramIndex][eventName] = par; } else { currentPage.params.push({ [eventName]: par }) } routerEventEmitter.emit(`${location.pathname}.${eventName}`, par); }, /** * @method on 事件监听器 * @param eventName {String} 事件名称 * @param callback {Function} 监听函数 * */ on(eventName, callback) { if (eventName) { routerEventEmitter.addOnceListener(`${location.pathname}.${eventName}`, callback); } }, /** * @method eventOn events事件绑定,主要用于页面返回传参 * @param eventName {String} 事件名称 * @param callback {Function} 监听函数 * */ eventOn(eventName, callback) { this.on(`events.${eventName}`, callback); }, /** * @method eventEmit events事件发射器,主要用于页面返回传参 * @param eventName {String} 事件名 * @param par {Any} 传给监听事件的参数 * */ eventEmit(eventName, par) { routerEventEmitter.emit(`${location.pathname}.events.${eventName}`, par); }, /** * @method update 更新路由 * @param pathName {String} 路由name * */ update(pathName) { const pageIndex = this.currentPages.findIndex((element) => element.pathName == pathName); let routerInfo = { pathName: pathName, params: [], //emit传递的参数集合 cache: true //页面是否缓存 }; if (pageIndex > -1) { //如果已存在路由直接替换原有信息 this.currentPages[pageIndex] = routerInfo; } else { //如果不存在路由添加路由信息 this.currentPages.push(routerInfo); } this.deleteHistory(pathName); }, /** * @method delete 移除页面路由 * @param delta {Number} 返回的页面数 * */ delete(delta) { const historyPages = this.currentPages.splice(this.currentPages.length - delta, delta); this.currentPages[this.currentPages.length - 1].cache = true; if (this.currentPages.length > 1) { this.historyPages.unshift(...historyPages); } else { //当前列表只有一个时,说明此时是在tabBar页,相当于重新开始路由跳转,需清空已回退页面列表 this.historyPages = [...historyPages]; } }, /** * @method deleteHistory 移除页面历史路由 * @param pathName {String} 路由名字 * @param addCurrentPages {Boolean} 是否添加到当前路由 * */ deleteHistory(pathName,addCurrentPages) { if (this.historyPages.length) { const spliceCount = this.historyPages.findIndex((element) => element.pathName == pathName); const historyPages = this.historyPages.splice(0, spliceCount + 1); if(addCurrentPages) { historyPages.forEach((element)=>{ element.cache = true }); this.currentPages.push(...historyPages) } } }, /** * @method updateCacheStatus 更新某个页面缓存状态 * @param pathName 路由名 * */ updateCacheStatus(pathName) { this.currentPages.forEach((element)=>{ if(element.pathName == pathName){ element.cache = true; } }) }, /** * @method resetCacheStatus 重置页面缓存状态 * @description 用于页面刷新时 * */ resetCacheStatus() { const pathName = location.pathname.substring(1); if (this.currentPages.length) { this.currentPages.forEach((element) => { element.cache = pathName == element.pathName ? true : false; }) } if (this.historyPages.length) { this.historyPages.forEach((element) => { element.cache = pathName == element.pathName ? true : false; }) } } }, persist: {//pinia持久化配置,默认sessionStorage enabled: true } }); export default useRouterStore