vue-app-sdk
Version:
247 lines (246 loc) • 7.79 kB
JavaScript
"use strict";
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const index = require("../../utils/index2.cjs");
require("../../vendors/nice-fns/dist/compactObject.cjs");
require("../../vendors/nice-fns/dist/pascalCase.cjs");
const vue = require("vue");
require("../../vendors/easy-hookable/dist/callers.cjs");
require("../../vendors/easy-hookable/dist/ContextHelper.cjs");
const Router = require("../../core/Router.cjs");
require("vue-router");
require("../Tabs/Tabs.cjs");
const isFunction = require("../../vendors/lodash-es/isFunction.cjs");
const isString = require("../../vendors/lodash-es/isString.cjs");
const once = require("../../vendors/lodash-es/once.cjs");
const KEEP_ALIVE_ID = Symbol("keep alive");
const beforeRouteDefaults = {
add: () => true,
remove: () => true
};
class KeepAlive {
constructor(options = {}) {
__publicField(this, "id", KEEP_ALIVE_ID);
/**
* 缓存的组件名称列表
*/
__publicField(this, "_values", vue.shallowRef(/* @__PURE__ */ new Set()));
/**
* 是否自动模式
*/
__publicField(this, "_isAuto");
/**
* 缓存保鲜定时器
*/
__publicField(this, "_staleTimer", null);
/**
* 缓存时间记录
*/
__publicField(this, "_timeRecord", {});
/**
* 更新缓存记录时间
*/
__publicField(this, "_updateTime", (value) => {
this._timeRecord[value] = Date.now();
});
/**
* 移除缓存时间记录
*/
__publicField(this, "_removeTime", (value) => {
delete this._timeRecord[value];
});
/**
* 启动缓存保鲜定时器
*/
__publicField(this, "startStaleTimer", () => {
const { staleTime } = this.options;
if (typeof staleTime !== "number")
throw new Error("staleTime must be a number");
if (staleTime <= 0)
return;
this.stopStaleTimer();
this.clearExpired();
this._staleTimer = setTimeout(this.startStaleTimer, staleTime);
});
/**
* 停止缓存保鲜定时器
*/
__publicField(this, "stopStaleTimer", () => {
if (this._staleTimer) {
clearTimeout(this._staleTimer);
this._staleTimer = null;
}
});
/**
* 清理过期缓存,设置 `options.staleTime > 0` 后有效
*/
__publicField(this, "clearExpired", () => {
const { staleTime } = this.options;
if (typeof staleTime !== "number" || staleTime <= 0)
return;
const newTimeRecord = {};
const values = [];
Object.entries(this._timeRecord).forEach(([key, time]) => {
if (Date.now() - time < staleTime)
values.push(key);
else
newTimeRecord[key] = time;
});
this._timeRecord = newTimeRecord;
this.set(values);
});
/**
* 切换自动模式
* @param value 状态值
*/
__publicField(this, "toggleAuto", (value = !this._isAuto.value) => {
this._isAuto.value = value;
return value;
});
/**
* 启用自动模式
*/
__publicField(this, "enableAuto", () => {
return this.toggleAuto(true);
});
/**
* 禁用自动模式
*/
__publicField(this, "disableAuto", () => {
return this.toggleAuto(false);
});
/**
* 清空缓存列表
*/
__publicField(this, "clear", () => {
this.set([]);
});
/**
* 设置缓存的名称列表,会覆盖旧列表
* @param values 缓存名称列表
*/
__publicField(this, "set", (values) => {
this._values.value = new Set(values);
});
__publicField(this, "install", (sdk) => {
const collector = once.default(() => {
sdk.hook("sdk:router:navigate", async (direction, to, from) => {
if (!this.isAuto)
return;
if (direction === Router.NavigationDirection.backward) {
const needRemoveMatched = from.matched.filter((m) => !to.matched.includes(m));
await Promise.all(needRemoveMatched.map(this.remove));
}
await Promise.all(to.matched.map(this.add));
});
});
const unwatch = vue.watch(
this._isAuto,
(value) => {
if (!value)
return;
vue.nextTick(() => unwatch());
collector();
},
{ immediate: true }
);
sdk.hook("sdk:cleanup", this.clear);
return () => {
unwatch();
this.stopStaleTimer();
};
});
this.options = options;
const { autoCollectAndClean = true } = options;
this._isAuto = vue.ref(vue.toValue(autoCollectAndClean));
if (vue.isRef(autoCollectAndClean) || isFunction.default(autoCollectAndClean))
vue.watch(autoCollectAndClean, this.toggleAuto);
this.add = this.add.bind(this);
this.remove = this.remove.bind(this);
this.refresh = this.refresh.bind(this);
if (options.staleTime != null)
this.startStaleTimer();
}
/**
* 缓存的组件名称列表
* @readonly
*/
get values() {
return [...this._values.value];
}
/**
* 是否自动模式
* @readonly
*/
get isAuto() {
return this._isAuto.value;
}
add(nameOrRoute) {
if (!nameOrRoute)
return;
const values = this._values.value;
if (isString.default(nameOrRoute)) {
if (!values.has(nameOrRoute)) {
values.add(nameOrRoute);
this._updateTime(nameOrRoute);
this.set(this.values);
}
} else if ("components" in nameOrRoute) {
const { beforeRouteAdd = beforeRouteDefaults.add } = this.options;
return Promise.resolve(beforeRouteAdd(nameOrRoute)).then((valid) => {
if (!valid)
return;
return index.resolveComponentNameByRoute(nameOrRoute).then(this.add);
});
} else if ("matched" in nameOrRoute) {
return this.add(nameOrRoute.matched.at(-1));
}
}
remove(nameOrRoute) {
if (!nameOrRoute)
return;
const values = this._values.value;
if (isString.default(nameOrRoute)) {
if (values.has(nameOrRoute)) {
values.delete(nameOrRoute);
this._removeTime(nameOrRoute);
this.set(this.values);
}
} else if ("components" in nameOrRoute) {
const beforeRouteRemove = this.options.beforeRouteRemove || beforeRouteDefaults.remove;
return Promise.resolve(beforeRouteRemove(nameOrRoute)).then((valid) => {
if (!valid)
return;
return index.resolveComponentNameByRoute(nameOrRoute).then(this.remove);
});
} else if ("matched" in nameOrRoute) {
return this.remove(nameOrRoute.matched.at(-1));
}
}
refresh(nameOrRoute) {
if (!nameOrRoute)
return;
if (isString.default(nameOrRoute)) {
this.remove(nameOrRoute);
vue.nextTick(() => {
this.add(nameOrRoute);
});
} else if ("components" in nameOrRoute) {
const {
beforeRouteAdd = beforeRouteDefaults.add,
beforeRouteRemove = beforeRouteDefaults.remove
} = this.options;
return Promise.all([beforeRouteAdd(nameOrRoute), beforeRouteRemove(nameOrRoute)]).then((results) => results.every(Boolean)).then((valid) => {
if (!valid)
return;
return index.resolveComponentNameByRoute(nameOrRoute).then(this.refresh);
});
} else if ("matched" in nameOrRoute) {
return this.refresh(nameOrRoute.matched.at(-1));
}
}
}
exports.KEEP_ALIVE_ID = KEEP_ALIVE_ID;
exports.KeepAlive = KeepAlive;