useRouterStore.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. import {defineStore} from "pinia";
  2. import router from "@/router.js";
  3. import useEventEmitter from "@hooks/useEventEmitter.js";
  4. import commonUtil from "@utility/commonUtil.js";
  5. import tabBarOption from "@/tabBar.js";
  6. export const routerEventEmitter = useEventEmitter();
  7. const tabBar = tabBarOption.map(el => el.pathName) //tabbar页面;
  8. /**
  9. * @method defaultCurrentPagesFun 默认当前路由
  10. * */
  11. const defaultCurrentPagesFun = () => {
  12. let defaultCurrentPages = [];
  13. if (tabBar.length) {
  14. defaultCurrentPages = [{
  15. pathName: tabBar[0],
  16. params: [],
  17. cache: true
  18. }]
  19. }
  20. return defaultCurrentPages;
  21. }
  22. /**
  23. * @method isNavigate 判断导航
  24. * @param navigateInfo { String | JSON } 导航信息
  25. * */
  26. const isNavigate = (navigateInfo) => {
  27. let isTabBar = false;
  28. let isNavStr = false;
  29. if (commonUtil.isStr(navigateInfo)) {
  30. isNavStr = true;
  31. if (tabBar.includes(navigateInfo)) {
  32. isTabBar = true;
  33. }
  34. } else {
  35. isNavStr = false;
  36. if (tabBar.includes(navigateInfo.pathName)) {
  37. isTabBar = true;
  38. }
  39. }
  40. return [isTabBar, isNavStr];
  41. };
  42. const useRouterStore = defineStore('routerStore', {
  43. state: () => ({
  44. currentPages: defaultCurrentPagesFun(),//当前已跳转页面列表
  45. historyPages: [] //当前已回退页面列表
  46. }),
  47. actions: {//actions是store的方法methods
  48. /***
  49. * @method navigateTo 保留当前页面,跳转某个页面,不能跳转跳转到tabBar页面
  50. * @param navigateInfo { String | JSON } 导航信息
  51. navigateInfo = pathName
  52. navigateInfo = {
  53. pathName:'', 路由名称
  54. success: ()=>{} 路由跳转成功函数
  55. }
  56. * */
  57. async navigateTo(navigateInfo) {
  58. const [isTabBar, isNavStr] = isNavigate(navigateInfo);
  59. if (!isTabBar) {
  60. let pathName = isNavStr ? navigateInfo : navigateInfo.pathName;
  61. await router.push(pathName);
  62. this.update(pathName);
  63. if (commonUtil.isFun(navigateInfo.success)) navigateInfo.success();
  64. }
  65. },
  66. /**
  67. * @method navigateBack 关闭当前页面,返回上一页面或多级页面
  68. * @param backInfo { Number | JSON } 导航信息 返回的页面数,默认1
  69. backInfo={
  70. delta: 1,
  71. success: ()=>{} 路由跳转成功函数
  72. }
  73. * */
  74. navigateBack(backInfo = 1) {
  75. let delta = backInfo;
  76. const backPageRouter = this.currentPages[this.currentPages.length - 2];
  77. this.updateCacheStatus(backPageRouter.pathName);
  78. //返回一个页面由路由监听处理,主要为了兼容浏览器自带的返回
  79. if (commonUtil.isJson(backInfo)) {
  80. delta = backInfo.delta || 1;
  81. }
  82. if (delta > 1) {
  83. router.go(-delta);
  84. this.delete(delta);
  85. } else {
  86. router.back();
  87. }
  88. // 返回页面,真实内容的渲染会慢一拍;这里用定时处理
  89. if (commonUtil.isFun(backInfo.success)) {
  90. const navigateBackTimeout = setTimeout(() => {
  91. backInfo.success();
  92. clearTimeout(navigateBackTimeout);
  93. }, 30)
  94. }
  95. },
  96. /***
  97. * @method switchTabBar 跳转到tabBar页面,并关闭其他所有非tabBar页面
  98. * @param navigateInfo { String | JSON } 导航信息
  99. navigateInfo = pathName
  100. navigateInfo = {
  101. pathName:'', 路由名称
  102. success: ()=>{} 路由跳转成功函数
  103. }
  104. * */
  105. async switchTabBar(navigateInfo) {
  106. const [isTabBar, isNavStr] = isNavigate(navigateInfo);
  107. if (isTabBar) {
  108. let pathName = isNavStr ? navigateInfo : navigateInfo.pathName;
  109. await router.replace(pathName);
  110. if (commonUtil.isFun(navigateInfo.success)) navigateInfo.success();
  111. this.currentPages = [{
  112. pathName: pathName,
  113. params: [], //emit传递的参数集合
  114. cache: true //页面是否缓存
  115. }];
  116. //跳转tabBar页,相当于重新开始路由跳转,需清空已回退页面列表
  117. this.historyPages = [];
  118. }
  119. },
  120. /***
  121. * @method redirectTo 关闭当前页面,跳转某个页面。但是不允许跳转到tabBar页面
  122. * @param navigateInfo { String | JSON } 导航信息
  123. navigateInfo = pathName
  124. navigateInfo = {
  125. pathName:'', 路由名称
  126. success: ()=>{} 路由跳转成功函数
  127. }
  128. * */
  129. async redirectTo(navigateInfo) {
  130. const [isTabBar, isNavStr] = isNavigate(navigateInfo);
  131. if (!isTabBar) {
  132. let pathName = isNavStr ? navigateInfo : navigateInfo.pathName;
  133. await router.replace(pathName);
  134. if (commonUtil.isFun(navigateInfo.success)) navigateInfo.success();
  135. this.deleteHistory(pathName);
  136. }
  137. },
  138. /**
  139. * @method emit 触发特定事件,并依次调用与该事件关联的所有监听器函数
  140. * @param eventName {String} 事件名
  141. * @param par {Any} 传给监听事件的参数
  142. * */
  143. emit(eventName, par) {
  144. const currentPage = this.currentPages[this.currentPages.length - 1];
  145. const paramIndex = currentPage.params?.findIndex(el => Reflect.ownKeys(el)[0] == eventName)
  146. if (paramIndex > -1) {
  147. currentPage.params[paramIndex][eventName] = par;
  148. } else {
  149. currentPage.params.push({
  150. [eventName]: par
  151. })
  152. }
  153. routerEventEmitter.emit(`${location.pathname}.${eventName}`, par);
  154. },
  155. /**
  156. * @method on 事件监听器
  157. * @param eventName {String} 事件名称
  158. * @param callback {Function} 监听函数
  159. * */
  160. on(eventName, callback) {
  161. if (eventName) {
  162. routerEventEmitter.addOnceListener(`${location.pathname}.${eventName}`, callback);
  163. }
  164. },
  165. /**
  166. * @method eventOn events事件绑定,主要用于页面返回传参
  167. * @param eventName {String} 事件名称
  168. * @param callback {Function} 监听函数
  169. * */
  170. eventOn(eventName, callback) {
  171. this.on(`events.${eventName}`, callback);
  172. },
  173. /**
  174. * @method eventEmit events事件发射器,主要用于页面返回传参
  175. * @param eventName {String} 事件名
  176. * @param par {Any} 传给监听事件的参数
  177. * */
  178. eventEmit(eventName, par) {
  179. routerEventEmitter.emit(`${location.pathname}.events.${eventName}`, par);
  180. },
  181. /**
  182. * @method update 更新路由
  183. * @param pathName {String} 路由name
  184. * */
  185. update(pathName) {
  186. const pageIndex = this.currentPages.findIndex((element) => element.pathName == pathName);
  187. let routerInfo = {
  188. pathName: pathName,
  189. params: [], //emit传递的参数集合
  190. cache: true //页面是否缓存
  191. };
  192. if (pageIndex > -1) {
  193. //如果已存在路由直接替换原有信息
  194. this.currentPages[pageIndex] = routerInfo;
  195. } else {
  196. //如果不存在路由添加路由信息
  197. this.currentPages.push(routerInfo);
  198. }
  199. this.deleteHistory(pathName);
  200. },
  201. /**
  202. * @method delete 移除页面路由
  203. * @param delta {Number} 返回的页面数
  204. * */
  205. delete(delta) {
  206. const historyPages = this.currentPages.splice(this.currentPages.length - delta, delta);
  207. this.currentPages[this.currentPages.length - 1].cache = true;
  208. if (this.currentPages.length > 1) {
  209. this.historyPages.unshift(...historyPages);
  210. } else {
  211. //当前列表只有一个时,说明此时是在tabBar页,相当于重新开始路由跳转,需清空已回退页面列表
  212. this.historyPages = [...historyPages];
  213. }
  214. },
  215. /**
  216. * @method deleteHistory 移除页面历史路由
  217. * @param pathName {String} 路由名字
  218. * @param addCurrentPages {Boolean} 是否添加到当前路由
  219. * */
  220. deleteHistory(pathName,addCurrentPages) {
  221. if (this.historyPages.length) {
  222. const spliceCount = this.historyPages.findIndex((element) => element.pathName == pathName);
  223. const historyPages = this.historyPages.splice(0, spliceCount + 1);
  224. if(addCurrentPages) {
  225. historyPages.forEach((element)=>{
  226. element.cache = true
  227. });
  228. this.currentPages.push(...historyPages)
  229. }
  230. }
  231. },
  232. /**
  233. * @method updateCacheStatus 更新某个页面缓存状态
  234. * @param pathName 路由名
  235. * */
  236. updateCacheStatus(pathName) {
  237. this.currentPages.forEach((element)=>{
  238. if(element.pathName == pathName){
  239. element.cache = true;
  240. }
  241. })
  242. },
  243. /**
  244. * @method resetCacheStatus 重置页面缓存状态
  245. * @description 用于页面刷新时
  246. * */
  247. resetCacheStatus() {
  248. const pathName = location.pathname.substring(1);
  249. if (this.currentPages.length) {
  250. this.currentPages.forEach((element) => {
  251. element.cache = pathName == element.pathName ? true : false;
  252. })
  253. }
  254. if (this.historyPages.length) {
  255. this.historyPages.forEach((element) => {
  256. element.cache = pathName == element.pathName ? true : false;
  257. })
  258. }
  259. }
  260. },
  261. persist: {//pinia持久化配置,默认sessionStorage
  262. enabled: true
  263. }
  264. });
  265. export default useRouterStore