perf: optimize the closing jump logic of tabs
This commit is contained in:
107
packages/@core/base/shared/src/utils/__tests__/stack.test.ts
Normal file
107
packages/@core/base/shared/src/utils/__tests__/stack.test.ts
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
import { beforeEach, describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
|
import { createStack, Stack } from '../stack';
|
||||||
|
|
||||||
|
describe('stack', () => {
|
||||||
|
let stack: Stack<number>;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
stack = new Stack<number>();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('push & size should work', () => {
|
||||||
|
stack.push(1, 2);
|
||||||
|
|
||||||
|
expect(stack.size).toBe(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('peek should return top element without removing it', () => {
|
||||||
|
stack.push(1, 2);
|
||||||
|
|
||||||
|
expect(stack.peek()).toBe(2);
|
||||||
|
expect(stack.size).toBe(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('pop should remove and return top element', () => {
|
||||||
|
stack.push(1, 2);
|
||||||
|
|
||||||
|
expect(stack.pop()).toBe(2);
|
||||||
|
expect(stack.size).toBe(1);
|
||||||
|
expect(stack.peek()).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('pop on empty stack should return undefined', () => {
|
||||||
|
expect(stack.pop()).toBeUndefined();
|
||||||
|
expect(stack.peek()).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('clear should remove all elements', () => {
|
||||||
|
stack.push(1, 2);
|
||||||
|
|
||||||
|
stack.clear();
|
||||||
|
|
||||||
|
expect(stack.size).toBe(0);
|
||||||
|
expect(stack.peek()).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('toArray should return a shallow copy', () => {
|
||||||
|
stack.push(1, 2);
|
||||||
|
|
||||||
|
const arr = stack.toArray();
|
||||||
|
arr.push(3);
|
||||||
|
|
||||||
|
expect(stack.size).toBe(2);
|
||||||
|
expect(stack.toArray()).toEqual([1, 2]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('dedup should remove existing item before push', () => {
|
||||||
|
stack.push(1, 2, 1);
|
||||||
|
|
||||||
|
expect(stack.toArray()).toEqual([2, 1]);
|
||||||
|
expect(stack.size).toBe(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('dedup = false should allow duplicate items', () => {
|
||||||
|
const s = new Stack<number>(false);
|
||||||
|
|
||||||
|
s.push(1, 1, 1);
|
||||||
|
|
||||||
|
expect(s.toArray()).toEqual([1, 1, 1]);
|
||||||
|
expect(s.size).toBe(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('remove should delete all matching items', () => {
|
||||||
|
stack.push(1, 2, 1);
|
||||||
|
|
||||||
|
stack.remove(1);
|
||||||
|
|
||||||
|
expect(stack.toArray()).toEqual([2]);
|
||||||
|
expect(stack.size).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('maxSize should limit stack capacity', () => {
|
||||||
|
const s = new Stack<number>(true, 3);
|
||||||
|
|
||||||
|
s.push(1, 2, 3, 4);
|
||||||
|
|
||||||
|
expect(s.toArray()).toEqual([2, 3, 4]);
|
||||||
|
expect(s.size).toBe(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('dedup + maxSize should work together', () => {
|
||||||
|
const s = new Stack<number>(true, 3);
|
||||||
|
|
||||||
|
s.push(1, 2, 3, 2); // 去重并重新入栈
|
||||||
|
|
||||||
|
expect(s.toArray()).toEqual([1, 3, 2]);
|
||||||
|
expect(s.size).toBe(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('createStack should create a stack instance', () => {
|
||||||
|
const s = createStack<number>(true, 2);
|
||||||
|
|
||||||
|
s.push(1, 2, 3);
|
||||||
|
|
||||||
|
expect(s.toArray()).toEqual([2, 3]);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -8,6 +8,7 @@ export * from './letter';
|
|||||||
export * from './merge';
|
export * from './merge';
|
||||||
export * from './nprogress';
|
export * from './nprogress';
|
||||||
export * from './resources';
|
export * from './resources';
|
||||||
|
export * from './stack';
|
||||||
export * from './state-handler';
|
export * from './state-handler';
|
||||||
export * from './to';
|
export * from './to';
|
||||||
export * from './tree';
|
export * from './tree';
|
||||||
|
|||||||
103
packages/@core/base/shared/src/utils/stack.ts
Normal file
103
packages/@core/base/shared/src/utils/stack.ts
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
/**
|
||||||
|
* @zh_CN 栈数据结构
|
||||||
|
*/
|
||||||
|
export class Stack<T> {
|
||||||
|
/**
|
||||||
|
* @zh_CN 栈内元素数量
|
||||||
|
*/
|
||||||
|
get size() {
|
||||||
|
return this.items.length;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @zh_CN 是否去重
|
||||||
|
*/
|
||||||
|
private readonly dedup: boolean;
|
||||||
|
/**
|
||||||
|
* @zh_CN 栈内元素
|
||||||
|
*/
|
||||||
|
private items: T[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh_CN 栈的最大容量
|
||||||
|
*/
|
||||||
|
private readonly maxSize?: number;
|
||||||
|
|
||||||
|
constructor(dedup = true, maxSize?: number) {
|
||||||
|
this.maxSize = maxSize;
|
||||||
|
this.dedup = dedup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh_CN 清空栈内元素
|
||||||
|
*/
|
||||||
|
clear() {
|
||||||
|
this.items.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh_CN 查看栈顶元素
|
||||||
|
* @returns 栈顶元素
|
||||||
|
*/
|
||||||
|
peek(): T | undefined {
|
||||||
|
return this.items[this.items.length - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh_CN 出栈
|
||||||
|
* @returns 栈顶元素
|
||||||
|
*/
|
||||||
|
pop(): T | undefined {
|
||||||
|
return this.items.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh_CN 入栈
|
||||||
|
* @param items 要入栈的元素
|
||||||
|
*/
|
||||||
|
push(...items: T[]) {
|
||||||
|
items.forEach((item) => {
|
||||||
|
// 去重
|
||||||
|
if (this.dedup) {
|
||||||
|
const index = this.items.indexOf(item);
|
||||||
|
if (index !== -1) {
|
||||||
|
this.items.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.items.push(item);
|
||||||
|
if (this.maxSize && this.items.length > this.maxSize) {
|
||||||
|
this.items.splice(0, this.items.length - this.maxSize);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @zh_CN 移除栈内元素
|
||||||
|
* @param itemList 要移除的元素列表
|
||||||
|
*/
|
||||||
|
remove(...itemList: T[]) {
|
||||||
|
this.items = this.items.filter((i) => !itemList.includes(i));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @zh_CN 保留栈内元素
|
||||||
|
* @param itemList 要保留的元素列表
|
||||||
|
*/
|
||||||
|
retain(itemList: T[]) {
|
||||||
|
this.items = this.items.filter((i) => itemList.includes(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh_CN 转换为数组
|
||||||
|
* @returns 栈内元素数组
|
||||||
|
*/
|
||||||
|
toArray(): T[] {
|
||||||
|
return [...this.items];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh_CN 创建一个栈实例
|
||||||
|
* @param dedup 是否去重
|
||||||
|
* @param maxSize 栈的最大容量
|
||||||
|
* @returns 栈实例
|
||||||
|
*/
|
||||||
|
export const createStack = <T>(dedup = true, maxSize?: number) =>
|
||||||
|
new Stack<T>(dedup, maxSize);
|
||||||
@@ -105,6 +105,7 @@ exports[`defaultPreferences immutability test > should not modify the config obj
|
|||||||
"showMaximize": true,
|
"showMaximize": true,
|
||||||
"showMore": true,
|
"showMore": true,
|
||||||
"styleType": "chrome",
|
"styleType": "chrome",
|
||||||
|
"visitHistory": true,
|
||||||
"wheelable": true,
|
"wheelable": true,
|
||||||
},
|
},
|
||||||
"theme": {
|
"theme": {
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ const defaultPreferences: Preferences = {
|
|||||||
showMaximize: true,
|
showMaximize: true,
|
||||||
showMore: true,
|
showMore: true,
|
||||||
styleType: 'chrome',
|
styleType: 'chrome',
|
||||||
|
visitHistory: true,
|
||||||
wheelable: true,
|
wheelable: true,
|
||||||
},
|
},
|
||||||
theme: {
|
theme: {
|
||||||
|
|||||||
@@ -224,6 +224,8 @@ interface TabbarPreferences {
|
|||||||
showMore: boolean;
|
showMore: boolean;
|
||||||
/** 标签页风格 */
|
/** 标签页风格 */
|
||||||
styleType: TabsStyleType;
|
styleType: TabsStyleType;
|
||||||
|
/** 是否开启访问历史记录 */
|
||||||
|
visitHistory: boolean;
|
||||||
/** 是否开启鼠标滚轮响应 */
|
/** 是否开启鼠标滚轮响应 */
|
||||||
wheelable: boolean;
|
wheelable: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ defineProps<{ disabled?: boolean }>();
|
|||||||
const tabbarEnable = defineModel<boolean>('tabbarEnable');
|
const tabbarEnable = defineModel<boolean>('tabbarEnable');
|
||||||
const tabbarShowIcon = defineModel<boolean>('tabbarShowIcon');
|
const tabbarShowIcon = defineModel<boolean>('tabbarShowIcon');
|
||||||
const tabbarPersist = defineModel<boolean>('tabbarPersist');
|
const tabbarPersist = defineModel<boolean>('tabbarPersist');
|
||||||
|
const tabbarVisitHistory = defineModel<boolean>('tabbarVisitHistory');
|
||||||
const tabbarDraggable = defineModel<boolean>('tabbarDraggable');
|
const tabbarDraggable = defineModel<boolean>('tabbarDraggable');
|
||||||
const tabbarWheelable = defineModel<boolean>('tabbarWheelable');
|
const tabbarWheelable = defineModel<boolean>('tabbarWheelable');
|
||||||
const tabbarStyleType = defineModel<string>('tabbarStyleType');
|
const tabbarStyleType = defineModel<string>('tabbarStyleType');
|
||||||
@@ -56,6 +57,13 @@ const styleItems = computed((): SelectOption[] => [
|
|||||||
<SwitchItem v-model="tabbarPersist" :disabled="!tabbarEnable">
|
<SwitchItem v-model="tabbarPersist" :disabled="!tabbarEnable">
|
||||||
{{ $t('preferences.tabbar.persist') }}
|
{{ $t('preferences.tabbar.persist') }}
|
||||||
</SwitchItem>
|
</SwitchItem>
|
||||||
|
<SwitchItem
|
||||||
|
v-model="tabbarVisitHistory"
|
||||||
|
:disabled="!tabbarEnable"
|
||||||
|
:tip="$t('preferences.tabbar.visitHistoryTip')"
|
||||||
|
>
|
||||||
|
{{ $t('preferences.tabbar.visitHistory') }}
|
||||||
|
</SwitchItem>
|
||||||
<NumberFieldItem
|
<NumberFieldItem
|
||||||
v-model="tabbarMaxCount"
|
v-model="tabbarMaxCount"
|
||||||
:disabled="!tabbarEnable"
|
:disabled="!tabbarEnable"
|
||||||
|
|||||||
@@ -120,6 +120,7 @@ const tabbarShowIcon = defineModel<boolean>('tabbarShowIcon');
|
|||||||
const tabbarShowMore = defineModel<boolean>('tabbarShowMore');
|
const tabbarShowMore = defineModel<boolean>('tabbarShowMore');
|
||||||
const tabbarShowMaximize = defineModel<boolean>('tabbarShowMaximize');
|
const tabbarShowMaximize = defineModel<boolean>('tabbarShowMaximize');
|
||||||
const tabbarPersist = defineModel<boolean>('tabbarPersist');
|
const tabbarPersist = defineModel<boolean>('tabbarPersist');
|
||||||
|
const tabbarVisitHistory = defineModel<boolean>('tabbarVisitHistory');
|
||||||
const tabbarDraggable = defineModel<boolean>('tabbarDraggable');
|
const tabbarDraggable = defineModel<boolean>('tabbarDraggable');
|
||||||
const tabbarWheelable = defineModel<boolean>('tabbarWheelable');
|
const tabbarWheelable = defineModel<boolean>('tabbarWheelable');
|
||||||
const tabbarStyleType = defineModel<string>('tabbarStyleType');
|
const tabbarStyleType = defineModel<string>('tabbarStyleType');
|
||||||
@@ -400,6 +401,7 @@ async function handleReset() {
|
|||||||
v-model:tabbar-draggable="tabbarDraggable"
|
v-model:tabbar-draggable="tabbarDraggable"
|
||||||
v-model:tabbar-enable="tabbarEnable"
|
v-model:tabbar-enable="tabbarEnable"
|
||||||
v-model:tabbar-persist="tabbarPersist"
|
v-model:tabbar-persist="tabbarPersist"
|
||||||
|
v-model:tabbar-visit-history="tabbarVisitHistory"
|
||||||
v-model:tabbar-show-icon="tabbarShowIcon"
|
v-model:tabbar-show-icon="tabbarShowIcon"
|
||||||
v-model:tabbar-show-maximize="tabbarShowMaximize"
|
v-model:tabbar-show-maximize="tabbarShowMaximize"
|
||||||
v-model:tabbar-show-more="tabbarShowMore"
|
v-model:tabbar-show-more="tabbarShowMore"
|
||||||
|
|||||||
@@ -68,6 +68,8 @@
|
|||||||
"showMore": "Show More Button",
|
"showMore": "Show More Button",
|
||||||
"showMaximize": "Show Maximize Button",
|
"showMaximize": "Show Maximize Button",
|
||||||
"persist": "Persist Tabs",
|
"persist": "Persist Tabs",
|
||||||
|
"visitHistory": "Visit History",
|
||||||
|
"visitHistoryTip": "When enabled, the tab bar records tab visit history. \nClosing the current tab will automatically select the last opened tab.",
|
||||||
"maxCount": "Max Count of Tabs",
|
"maxCount": "Max Count of Tabs",
|
||||||
"maxCountTip": "When the number of tabs exceeds the maximum,\nthe oldest tab will be closed.\n Set to 0 to disable count checking.",
|
"maxCountTip": "When the number of tabs exceeds the maximum,\nthe oldest tab will be closed.\n Set to 0 to disable count checking.",
|
||||||
"draggable": "Enable Draggable Sort",
|
"draggable": "Enable Draggable Sort",
|
||||||
|
|||||||
@@ -68,6 +68,8 @@
|
|||||||
"showMore": "显示更多按钮",
|
"showMore": "显示更多按钮",
|
||||||
"showMaximize": "显示最大化按钮",
|
"showMaximize": "显示最大化按钮",
|
||||||
"persist": "持久化标签页",
|
"persist": "持久化标签页",
|
||||||
|
"visitHistory": "访问历史记录",
|
||||||
|
"visitHistoryTip": "开启后,标签栏会记录标签访问历史\n关闭当前标签,会自动选中上一个打开的标签",
|
||||||
"maxCount": "最大标签数",
|
"maxCount": "最大标签数",
|
||||||
"maxCountTip": "每次打开新的标签时如果超过最大标签数,\n会自动关闭一个最先打开的标签\n设置为 0 则不限制",
|
"maxCountTip": "每次打开新的标签时如果超过最大标签数,\n会自动关闭一个最先打开的标签\n设置为 0 则不限制",
|
||||||
"draggable": "启动拖拽排序",
|
"draggable": "启动拖拽排序",
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ import { toRaw } from 'vue';
|
|||||||
|
|
||||||
import { preferences } from '@vben-core/preferences';
|
import { preferences } from '@vben-core/preferences';
|
||||||
import {
|
import {
|
||||||
|
createStack,
|
||||||
openRouteInNewWindow,
|
openRouteInNewWindow,
|
||||||
|
Stack,
|
||||||
startProgress,
|
startProgress,
|
||||||
stopProgress,
|
stopProgress,
|
||||||
} from '@vben-core/shared/utils';
|
} from '@vben-core/shared/utils';
|
||||||
@@ -47,8 +49,17 @@ interface TabbarState {
|
|||||||
* @zh_CN 更新时间,用于一些更新场景,使用watch深度监听的话,会损耗性能
|
* @zh_CN 更新时间,用于一些更新场景,使用watch深度监听的话,会损耗性能
|
||||||
*/
|
*/
|
||||||
updateTime?: number;
|
updateTime?: number;
|
||||||
|
/**
|
||||||
|
* @zh_CN 上一个标签页打开的标签
|
||||||
|
*/
|
||||||
|
visitHistory: Stack<string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh_CN 访问历史记录最大数量
|
||||||
|
*/
|
||||||
|
const MAX_VISIT_HISTORY = 50;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @zh_CN 访问权限相关
|
* @zh_CN 访问权限相关
|
||||||
*/
|
*/
|
||||||
@@ -62,6 +73,9 @@ export const useTabbarStore = defineStore('core-tabbar', {
|
|||||||
this.tabs = this.tabs.filter(
|
this.tabs = this.tabs.filter(
|
||||||
(item) => !keySet.has(getTabKeyFromTab(item)),
|
(item) => !keySet.has(getTabKeyFromTab(item)),
|
||||||
);
|
);
|
||||||
|
if (isVisitHistory()) {
|
||||||
|
this.visitHistory.remove(...keys);
|
||||||
|
}
|
||||||
|
|
||||||
await this.updateCacheTabs();
|
await this.updateCacheTabs();
|
||||||
},
|
},
|
||||||
@@ -166,6 +180,10 @@ export const useTabbarStore = defineStore('core-tabbar', {
|
|||||||
this.tabs.splice(tabIndex, 1, mergedTab);
|
this.tabs.splice(tabIndex, 1, mergedTab);
|
||||||
}
|
}
|
||||||
this.updateCacheTabs();
|
this.updateCacheTabs();
|
||||||
|
// 添加访问历史记录
|
||||||
|
if (isVisitHistory()) {
|
||||||
|
this.visitHistory.push(tab.key as string);
|
||||||
|
}
|
||||||
return tab;
|
return tab;
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
@@ -174,6 +192,12 @@ export const useTabbarStore = defineStore('core-tabbar', {
|
|||||||
async closeAllTabs(router: Router) {
|
async closeAllTabs(router: Router) {
|
||||||
const newTabs = this.tabs.filter((tab) => isAffixTab(tab));
|
const newTabs = this.tabs.filter((tab) => isAffixTab(tab));
|
||||||
this.tabs = newTabs.length > 0 ? newTabs : [...this.tabs].splice(0, 1);
|
this.tabs = newTabs.length > 0 ? newTabs : [...this.tabs].splice(0, 1);
|
||||||
|
// 设置访问历史记录
|
||||||
|
if (isVisitHistory()) {
|
||||||
|
this.visitHistory.retain(
|
||||||
|
this.tabs.map((item) => getTabKeyFromTab(item)),
|
||||||
|
);
|
||||||
|
}
|
||||||
await this._goToDefaultTab(router);
|
await this._goToDefaultTab(router);
|
||||||
this.updateCacheTabs();
|
this.updateCacheTabs();
|
||||||
},
|
},
|
||||||
@@ -249,12 +273,44 @@ export const useTabbarStore = defineStore('core-tabbar', {
|
|||||||
*/
|
*/
|
||||||
async closeTab(tab: TabDefinition, router: Router) {
|
async closeTab(tab: TabDefinition, router: Router) {
|
||||||
const { currentRoute } = router;
|
const { currentRoute } = router;
|
||||||
|
const currentTabKey = getTabKey(currentRoute.value);
|
||||||
// 关闭不是激活选项卡
|
// 关闭不是激活选项卡
|
||||||
if (getTabKey(currentRoute.value) !== getTabKeyFromTab(tab)) {
|
if (currentTabKey !== getTabKeyFromTab(tab)) {
|
||||||
this._close(tab);
|
this._close(tab);
|
||||||
this.updateCacheTabs();
|
this.updateCacheTabs();
|
||||||
|
// 移除访问历史记录
|
||||||
|
if (isVisitHistory()) {
|
||||||
|
this.visitHistory.remove(getTabKeyFromTab(tab));
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (this.getTabs.length <= 1) {
|
||||||
|
console.error('Failed to close the tab; only one tab remains open.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 从访问历史记录中移除当前关闭的tab
|
||||||
|
if (isVisitHistory()) {
|
||||||
|
this.visitHistory.remove(currentTabKey);
|
||||||
|
this._close(tab);
|
||||||
|
|
||||||
|
let previousTab: TabDefinition | undefined;
|
||||||
|
let previousTabKey: string | undefined;
|
||||||
|
while (true) {
|
||||||
|
previousTabKey = this.visitHistory.pop();
|
||||||
|
if (!previousTabKey) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
previousTab = this.getTabByKey(previousTabKey);
|
||||||
|
if (previousTab) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await (previousTab
|
||||||
|
? this._goToTab(previousTab, router)
|
||||||
|
: this._goToDefaultTab(router));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 未开启访问历史记录,直接跳转下一个或上一个tab
|
||||||
const index = this.getTabs.findIndex(
|
const index = this.getTabs.findIndex(
|
||||||
(item) => getTabKeyFromTab(item) === getTabKey(currentRoute.value),
|
(item) => getTabKeyFromTab(item) === getTabKey(currentRoute.value),
|
||||||
);
|
);
|
||||||
@@ -270,8 +326,6 @@ export const useTabbarStore = defineStore('core-tabbar', {
|
|||||||
} else if (before) {
|
} else if (before) {
|
||||||
this._close(tab);
|
this._close(tab);
|
||||||
await this._goToTab(before, router);
|
await this._goToTab(before, router);
|
||||||
} else {
|
|
||||||
console.error('Failed to close the tab; only one tab remains open.');
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -527,11 +581,12 @@ export const useTabbarStore = defineStore('core-tabbar', {
|
|||||||
persist: [
|
persist: [
|
||||||
// tabs不需要保存在localStorage
|
// tabs不需要保存在localStorage
|
||||||
{
|
{
|
||||||
pick: ['tabs'],
|
pick: ['tabs', 'visitHistory'],
|
||||||
storage: sessionStorage,
|
storage: sessionStorage,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
state: (): TabbarState => ({
|
state: (): TabbarState => ({
|
||||||
|
visitHistory: createStack<string>(true, MAX_VISIT_HISTORY),
|
||||||
cachedTabs: new Set(),
|
cachedTabs: new Set(),
|
||||||
dragEndIndex: 0,
|
dragEndIndex: 0,
|
||||||
excludeCachedTabs: new Set(),
|
excludeCachedTabs: new Set(),
|
||||||
@@ -628,6 +683,13 @@ function getTabKey(tab: RouteLocationNormalized | RouteRecordNormalized) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh_CN 是否开启访问历史记录
|
||||||
|
*/
|
||||||
|
function isVisitHistory() {
|
||||||
|
return preferences.tabbar.visitHistory;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从tab获取tab页的key
|
* 从tab获取tab页的key
|
||||||
* 如果tab没有key,那么就从route获取key
|
* 如果tab没有key,那么就从route获取key
|
||||||
|
|||||||
Reference in New Issue
Block a user