UNPKG

vue-app-sdk

Version:
203 lines (202 loc) 6.46 kB
"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 ROUTER_SCROLLER_ID = Symbol("router scroller"); class RouterScroller { constructor(options) { __publicField(this, "id", ROUTER_SCROLLER_ID); /** * AppSDK 实例 */ __publicField(this, "_sdk"); /** * 滚动位置记录 */ __publicField(this, "positions", /* @__PURE__ */ new Map()); /** * 是否自动模式 */ __publicField(this, "_isAuto"); /** * 切换自动模式 * @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); }); /** * 由于 `Transition` 动画可能导致元素自动还原滚动无效,此时可手动触发还原滚动 * @example * ```html * <script setup lang="ts"> * import { useAppSDK, ROUTER_SCROLLER_ID } from 'vue-app-sdk' * * const routerScroller = useAppSDK().getPlugin(ROUTER_SCROLLER_ID)! * * function handleAfterEnter() { * routerScroller.trigger() * } * <\/script> * * <template> * <Transition @after-enter="handleAfterEnter"> * ... * </Transition> * </template> * ``` */ __publicField(this, "trigger", () => { const { router } = this._sdk; const route = router.currentRoute.value; const key = route.fullPath; return this.applyPositions( route, route, this.positions.get(key), Router.NavigationDirection.unchanged, true ); }); /** * 获取滚动元素 * @param selector 选择器 * @returns 滚动元素 */ __publicField(this, "querySelector", (selector) => { if (typeof window === "undefined") return void 0; if (selector === "body") return document.body; if (selector === "window") return window; return document.querySelector(selector); }); /** * 获取滚动位置 * @param el 滚动元素 * @returns 滚动位置 */ __publicField(this, "getScrollPosition", (el) => { if (el instanceof Window) return { left: window.scrollX, top: window.scrollY }; else return { left: el.scrollLeft, top: el.scrollTop }; }); /** * 捕获滚动位置 */ __publicField(this, "capturePositions", () => { const pos = {}; for (const [selector] of Object.entries(this.options.selectors)) { const element = this.querySelector(selector); if (!element) continue; pos[selector] = this.getScrollPosition(element); } return pos; }); /** * 还原滚动位置 * @param to 目标路由 * @param from 来源路由 * @param position 滚动位置 * @param direction 导航方向 * @param isManual 是否手动触发 */ __publicField(this, "applyPositions", async (to, from, position, direction, isManual = false) => { for (const [selector, handler] of Object.entries(this.options.selectors)) { const element = this.querySelector(selector); if (!element) continue; let pos = position == null ? void 0 : position[selector]; if (isFunction.default(handler)) { const result = await handler({ to, from, element, selector, direction, savedPosition: pos, isManual }); if (!result) continue; if (result !== true) pos = result; } else if (handler === true) { if (this.options.scrollOnlyBackward && direction !== Router.NavigationDirection.backward) pos = void 0; } element.scrollTo({ behavior: this.options.behavior, ...pos || { top: 0, left: 0 } }); } }); __publicField(this, "install", (sdk) => { this._sdk = sdk; const { router } = sdk; if (router.options.scrollBehavior) { index.logger.warn( '"scrollBehavior" options in Vue Router is overwritten by "RouterScroller" plugin, you can remove it from "createRouter()".' ); } router.options.scrollBehavior = () => { }; router.beforeResolve((to, from) => { var _a; if (((_a = history.state) == null ? void 0 : _a.current) === to.fullPath) return; if (!this.isAuto) return; const pos = this.capturePositions(); this.positions.set(from.fullPath, pos); }); sdk.hook("sdk:router:navigate", (direction, to, from) => { if (!this.isAuto) return; const pos = this.positions.get(to.fullPath); vue.nextTick(() => this.applyPositions(to, from, pos, direction, false)); }); sdk.hook("sdk:cleanup", () => this.positions.clear()); }); this.options = options; const { autoCollect = true } = options; this._isAuto = vue.ref(vue.toValue(autoCollect)); if (vue.isRef(autoCollect) || isFunction.default(autoCollect)) vue.watch(autoCollect, this.toggleAuto); } /** * 是否自动模式 * @readonly */ get isAuto() { return this._isAuto.value; } } exports.ROUTER_SCROLLER_ID = ROUTER_SCROLLER_ID; exports.RouterScroller = RouterScroller;