| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- import { ref, toRefs, readonly } from 'vue'
- import { createRouter, RouterOptions, RouteRecordRaw, RouteLocationNormalized } from 'vue-router'
- interface HistoryState {
- history: RouteLocationNormalized[]; // 已访问的路由列表
- 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>({
- history: [],
- excludeViews: [],
- actionName: '',
- transitionName: '',
- goStep: 0,
- })
- /** 只读状态 */
- state;
- constructor() {
- const state = sessionStorage.getItem(this.storageKey);
- if (state) {
- this._state.value = JSON.parse(state);
- }
- this.state = readonly(toRefs(this._state.value));
- }
- /**
- * 创建路由
- * @param options
- * @returns
- */
- create = (options: RouterOptions) => {
- const router = createRouter(options);
- const { push, replace, go, forward, back } = router;
- const { actionName, goStep } = toRefs(this._state.value);
- // 添加
- 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(() => {
- const { excludeViews } = toRefs(this._state.value);
- excludeViews.value = [];
- })
- return router;
- }
- /**
- * 添加历史记录
- * @param route
- */
- private addHistory = (route: RouteLocationNormalized) => {
- const { history, excludeViews, actionName, transitionName, goStep } = toRefs(this._state.value);
- // 如果是替换动作,必定是前进
- if (actionName.value === 'replace') {
- const lastIndex = history.value.length - 1;
- const lastView = history.value[lastIndex];
- if (lastView) {
- excludeViews.value.push(lastView.name as string);
- history.value[lastIndex] = route; // 更新最后一条记录
- } else {
- history.value.push(route);
- }
- transitionName.value = 'route-in'; // 前进动画
- } else {
- // 倒序查找路由所在的位置
- const index = (() => {
- for (let i = history.value.length - 1; i >= 0; i--) {
- if (history.value[i].fullPath === route.fullPath) {
- return i;
- }
- }
- return -1;
- })();
- if (index > -1) {
- if (actionName.value === 'push') {
- history.value.push(route);
- transitionName.value = 'route-in'; //前进动画
- } else {
- if (history.value.length > 1) {
- const i = index + 1;
- const n = history.value.length - i;
- excludeViews.value = history.value.map((e) => e.name).slice(-n) as string[]; // 返回数组最后位置开始的n个元素
- history.value.splice(i, n); // 从i位置开始删除后面所有元素(包括i)
- }
- transitionName.value = 'route-out'; //后退动画
- }
- } else {
- if (goStep.value < 0) {
- const start = history.value.length + goStep.value
- if (start) {
- history.value.splice(start)
- }
- }
- // 忽略重定向的页面
- if (route.redirectedFrom) {
- transitionName.value = 'route-in'; // 前进动画
- } else {
- history.value.push(route);
- if (history.value.length > 1) {
- transitionName.value = 'route-in'; // 前进动画
- }
- }
- }
- }
- actionName.value = '';
- goStep.value = 0
- sessionStorage.setItem(this.storageKey, JSON.stringify(this._state.value));
- }
- })
|