| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- import { ref, toRefs } from 'vue'
- import { createRouter, RouterOptions, RouteRecordRaw, RouteLocationNormalized } from 'vue-router'
- interface historyRoute {
- name: string;
- fullPath: string;
- }
- interface HistoryState {
- historyRoutes: historyRoute[]; // 历史路由列表
- excludeViews: string[]; // 不缓存的视图
- actionName: '' | 'push' | 'replace' | 'forward' | 'back'; // 当前路由动作
- transitionName: '' | 'route-out' | 'route-in'; // 前进后退动画
- goStep: number; // 前进后退步数
- }
- export default new (class {
- private storageKey = 'history_mobile'
- private state = ref<HistoryState>({
- historyRoutes: [],
- excludeViews: [],
- actionName: '',
- transitionName: '',
- goStep: 0
- })
- constructor() {
- const state = sessionStorage.getItem(this.storageKey)
- if (state) {
- // 合并赋值,防止 sessionStorage 获取的值有问题
- this.state.value = {
- ...this.state.value,
- ...JSON.parse(state)
- }
- }
- }
- getState() {
- return this.state.value
- }
- getStateRef() {
- return toRefs(this.state.value)
- }
- /**
- * 创建路由
- * @param options
- * @returns
- */
- create = (options: RouterOptions) => {
- const router = createRouter(options)
- const { push, replace, go, forward, back } = router
- const { excludeViews, actionName, goStep } = this.getStateRef()
- // 添加
- router.push = (to: RouteRecordRaw) => {
- actionName.value = 'push'
- return push(to)
- }
- // 替换
- router.replace = (to: RouteRecordRaw) => {
- actionName.value = 'replace'
- return replace(to)
- }
- // 前进后退
- router.go = (delta: number) => {
- goStep.value = delta
- if (delta > 0) {
- actionName.value = 'forward'
- }
- if (delta < 0) {
- actionName.value = 'back'
- }
- go(delta)
- }
- // 前进
- router.forward = () => {
- actionName.value = 'forward'
- forward()
- }
- // 后退
- router.back = () => {
- actionName.value = 'back'
- back()
- }
- router.beforeResolve((to) => {
- this.addHistory(to)
- })
- router.afterEach(() => {
- excludeViews.value = []
- })
- return router
- }
- /**
- * 添加历史记录
- * @param route
- */
- private addHistory = (route: RouteLocationNormalized) => {
- const { historyRoutes, excludeViews, actionName, transitionName, goStep } = this.getStateRef()
- const newRoute = {
- name: route.name as string,
- fullPath: route.fullPath
- }
- // 如果是替换动作,必定是前进
- if (actionName.value === 'replace') {
- const lastIndex = historyRoutes.value.length - 1
- const lastView = historyRoutes.value[lastIndex]
- if (lastView) {
- excludeViews.value.push(lastView.name as string)
- historyRoutes.value[lastIndex] = newRoute // 更新最后一条记录
- } else {
- historyRoutes.value.push(newRoute)
- }
- transitionName.value = 'route-in' // 前进动画
- } else {
- // 倒序查找路由所在的位置
- const index = (() => {
- for (let i = historyRoutes.value.length - 1; i >= 0; i--) {
- if (historyRoutes.value[i].fullPath === route.fullPath) {
- return i
- }
- }
- return -1
- })()
- if (index > -1) {
- if (actionName.value === 'push') {
- historyRoutes.value.push(newRoute)
- transitionName.value = 'route-in' //前进动画
- } else {
- if (historyRoutes.value.length > 1) {
- const i = index + 1
- const n = historyRoutes.value.length - i
- excludeViews.value = historyRoutes.value.map((e) => e.name).slice(-n) // 返回数组最后位置开始的n个元素
- historyRoutes.value.splice(i, n) // 从i位置开始删除后面所有元素(包括i)
- }
- transitionName.value = 'route-out' //后退动画
- }
- } else {
- if (goStep.value < 0) {
- const start = historyRoutes.value.length + goStep.value
- if (start) {
- historyRoutes.value.splice(start)
- }
- }
- // 忽略重定向的页面
- if (route.redirectedFrom) {
- transitionName.value = 'route-in' // 前进动画
- } else {
- historyRoutes.value.push(newRoute)
- if (historyRoutes.value.length > 1) {
- transitionName.value = 'route-in' // 前进动画
- }
- }
- }
- }
- actionName.value = ''
- goStep.value = 0
- // 处理对象循环引用
- // const getCircularReplacer = () => {
- // const seen = new WeakSet()
- // return (key: string, value: unknown) => {
- // if (typeof value === 'object' && value !== null) {
- // if (seen.has(value)) {
- // return
- // }
- // seen.add(value)
- // }
- // return value
- // }
- // }
- sessionStorage.setItem(this.storageKey, JSON.stringify(this.state.value))
- }
- })
|