Lightweight Vue Router 4 plugin collection - extend routing capabilities with minimal overhead.
npm install @vue-spark/router-plugins轻量级 Vue Router 4 插件集合——以最小开销扩展路由能力。
> 从 v1.0.0 起,插件基于 vue-router-plugin-system 开发(弃用旧插件注册方式),详见其文档。
``sh`
npm i @vue-spark/router-plugins
#### 方式一:
`ts
import ScrollerPlugin from '@vue-spark/router-plugins/scroller'
// 初始化插件并安装
ScrollerPlugin({
selectors: ['.scrollable'],
}).install(router)
`
#### 方式二:
`ts
import ScrollerPlugin from '@vue-spark/router-plugins/scroller'
createApp(App)
// 先注册路由
.use(router)
// 再注册插件
.use(
ScrollerPlugin({
selectors: ['.scrollable'],
}),
)
`
#### 方式三:
`ts
import ScrollerPlugin from '@vue-spark/router-plugins/scroller'
import { createWebHistory } from 'vue-router'
import { createRouter } from 'vue-router-plugin-system'
const router = createRouter({
history: createWebHistory(),
routes: [],
plugins: [
// 初始化插件
ScrollerPlugin({
selectors: ['.scrollable'],
}),
],
})
`
用于在浏览器导航(前进/后退)时传递和恢复状态数据。
使用示例
`html
setup
lang="ts"
>
import { shallowRef, onActivated } from 'vue'
import { useRouter } from 'vue-router'
import type { PageState as ListDetailPageState } from './detail.vue'
interface Item {}
const list = shallowRef
const fetchList = async () => {
fetch('/api/list').then((res) => {
list.value = res.json()
})
}
// 立即请求
fetchList()
const router = useRouter()
const listDetailPageState = router.historyState
onActivated(() => {
listDetailPageState.withTake(({ outgoing }) => {
// 在需要时重新请求列表
outgoing?.refreshList && fetchList()
})
})
`
`html
setup
lang="ts"
>
import { useRouter } from 'vue-router'
export interface PageState {
outgoing?: {
refreshList?: boolean
}
}
const router = useRouter()
const pageState = router.historyState
function handleBack() {
// 设置延迟状态数据
pageState.setDeferred({ outgoing: { refreshList: true } })
router.back()
}
`
#### 类型定义
`tsrouter.options.history.state
interface HistoryStateManager
/**
* 等同于
*/
readonly raw: VueRouter.HistoryState
/**
* 状态所属的命名空间名称
*/
readonly namespace: string
/**
* 设置状态数据,会立即同步到 router.options.history.state,数据仅支持浅拷贝history.state
*
* 注意:当设置的数据无法被 结构化克隆({@link structuredClone})时,vue-router 会自动重置页面!
*/
set: (state: NoInfer
/**
* 仅设置内存里的状态数据,不会被更新到 router.options.history.statehistory.state
*
* 注意:虽然该函数不会更新 ,但是仍然不推荐设置无法被其结构化克隆({@link structuredClone})的数据!
*/
setMemory: HistoryStateManager
/**
* 延迟设置状态数据,会等待 router 下次导航成功时再同步到 router.options.history.state,history.state
* 可以在导航前多次调用,延迟设置的状态数据会放入缓冲区,无论下次导航成功或失败都会重置缓冲区
*
* 注意:当设置的数据无法被 结构化克隆({@link structuredClone})时,vue-router 会自动重置页面!router.options.history.state
*/
setDeferred: HistoryStateManager
/**
* 取消延迟设置的状态数据,直接重置缓冲区
*/
cancelDeferred: () => void
/**
* 立即同步缓冲区中的状态数据到
*/
applyDeferred: () => void
/**
* 获取状态数据
*/
get: () => NoInfer
/**
* 获取状态数据后执行回调函数
*/
withGet:
/**
* 获取状态数据并删除原始缓存
*/
take: () => NoInfer
/**
* 获取状态数据并删除原始缓存后执行回调函数
*/
withTake:
/**
* 销毁当前命名空间的状态数据
*/
destroy: () => void
}
interface Router {
historyState: {
readonly raw: VueRouter.HistoryState
}
}
`
用于模拟移动端导航方向(前进/后退/刷新),辅助动画与缓存控制。
使用示例
`html
setup
lang="ts"
>
import type { ResolveViewKey } from 'vue-router-better-view'
import { ref, shallowReactive } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter()
const transitionName = ref
const keepAliveValues = shallowReactive(new Set
const resolveViewKey: ResolveViewKey = (route) => {
return route.meta.title ? route.fullPath : null
}
router.navigationDirection.listen((direction, to, from) => {
switch (direction) {
case 'forward': {
transitionName.value = 'page-in'
keepAliveValues.add(to.fullPath)
break
}
case 'backward': {
transitionName.value = 'page-out'
keepAliveValues.delete(from.fullPath)
break
}
default: {
transitionName.value = undefined
keepAliveValues.delete(from.fullPath)
keepAliveValues.add(to.fullPath)
break
}
}
})
:resolve-view-key
>
:css="!!transitionName"
>
:key="route.fullPath"
/>
`
MemoryHistory 支持:在使用 createMemoryHistory() 时,由于 MemoryHistory 不提供浏览器历史记录的 delta 信息,插件会将所有导航操作(包括 push 和 replace)都识别为前进方向。如果需要在 MemoryHistory 环境下自定义方向识别逻辑,可以通过 directionResolver 选项来实现:
`ts`
const router = createRouter({
history: createMemoryHistory(),
routes,
plugins: [
NavigationDirectionPlugin({
directionResolver: ({ to, from, delta }) => {
// 自定义逻辑:根据路由变化判断方向
if (to.path !== from.path) {
// 可以根据具体业务逻辑判断是前进、后退还是替换
return NavigationDirection.unchanged // 或其他逻辑
}
return delta > 0 ? NavigationDirection.forward : NavigationDirection.backward
},
}),
],
})
#### 配置项
`ts`
interface NavigationDirectionOptions {
/**
* 导航方向解析器
*/
directionResolver?: NavigationDirectionResolver
}
#### 类型定义
`ts
enum NavigationDirection {
forward = 'forward',
backward = 'backward',
unchanged = 'unchanged',
}
interface INavigationDirection {
/**
* 当前导航方向,即最后一次导航方向
*/
currentDirection: ShallowRef
/**
* 设置下次导航方向,将会在下次导航成功时生效,导航失败时需要重新设置
*/
setNextDirection: (direction: NavigationDirection) => void
/**
* 监听导航方向变化,会在 onScopeDispose 时自动移除回调
*/
listen: (callback: NavigationDirectionCallback) => () => void
}
interface Router {
navigationDirection: INavigationDirection
}
`
自动保存并恢复滚动位置,适用于长页面或列表页。
使用示例
`ts
// router/index.ts
import ScrollerPlugin from '@vue-spark/router-plugins/scroller'
import { createWebHistory } from 'vue-router'
import { createRouter } from 'vue-router-plugin-system'
const router = createRouter({
history: createWebHistory(),
routes: [],
plugins: [
ScrollerPlugin({
// 设置滚动目标
selectors: ['.scrollable'],
}),
],
})
`
在搭配 组件使用时,需要在其 after-enter 事件时执行 router.scroller.trigger() 手动进行当前路由的滚动位置还原。
`html`
#### 配置项
`tswindow
interface ScrollerOptions {
/**
* 滚动行为
*/
behavior?: ScrollBehavior
/**
* 滚动元素选择器,支持特殊选择器 和 documenttrue
*/
selectors: string[]
/**
* 滚动位置处理函数
* - 返回 时使用记录的滚动位置ScrollPositionCoordinates
* - 返回假值时时跳过本次滚动
* - 返回 时使用自定义滚动位置`
*/
scrollHandler?: ScrollHandler
}
#### 类型定义
`ts
interface ScrollPositionCoordinates {
left?: number
top?: number
}
type ScrollPositionCoordinatesGroup = Record
interface Scroller {
/**
* 滚动位置记录
*/
positionsMap: ShallowReactive
interface Router {
scroller: Scroller
}
`
用于检测当前是否处于导航状态,适用于过渡动画或加载提示。
使用示例
`html`
#### 类型定义
`ts`
interface Router {
isNavigating: ShallowRef
}
记录上一个访问的路由信息,适合需要根据来源做逻辑判断的场景。
使用示例
`ts
const router = createRouter({...})
const originalBack = router.back
router.back = () => {
const currentRoute = router.currentRoute.value
const previousRoute = router.previousRoute.value
// 遇到前置路由为根路由且当前路由不是 TabBar 页面时,返回 TabBar 页面
if (previousRoute && previousRoute.fullPath === '/' && !currentRoute.meta.isTabBar) {
// 设置下次导航方向,用于变更导航动画
router.navigationDirection.setNextDirection(NavigationDirection.backward)
router.replace('/tab-bar')
return
}
originalBack()
}
`
#### 类型定义
`ts
interface PreviousRoute
extends Readonly<
Pick
> {}
interface Router {
previousRoute: ShallowRef
}
`
- ScrollerPluginscrollOnlyBackward
- 选项移除,使用 scrollHandler 处理滚动恢复。selectors
- 选项改为 string[]。HistoryStatePlugin
- HistoryStateManager
- 类型变更为 HistoryStateManager。router.historyState
- 不再支持默认命名空间。set
- 、setMemory、setDeferred、get、take 函数不再支持通过 key 设置/获取单个属性。set
- 、setMemory、setDeferred、get、take 函数类型变更,详见类型定义。
- 移除全部插件注册快捷方式,仅支持按需导入需要注册的插件。
- 插件基于 vue-router-plugin-system 开发(弃用旧插件注册方式),详见其文档。
- 单一插件导入路径改为 @vue-spark/router-plugins/[plugin-name]。selectors` 移除默认值并改为必填项。
- ScrollerPlugin 配置项