@gitlon/hooks
v0.1.1
Published
面向 Vue3 项目的页面生命周期插件:提供与 uniapp 行为一致的 onLoad / onShow
Maintainers
Readme
@gitlon/hooks
面向 Vue 3 SPA 的页面生命周期 Hooks,提供接近 uni-app 的 onLoad、onShow 使用方式。
安装
pnpm add @gitlon/hooks vue使用路由时安装 Vue Router:
pnpm add vue-router依赖要求:
| 依赖 | 版本 | 是否必需 |
| --- | --- | --- |
| vue | ^3.4.0 | 是 |
| vue-router | ^4.0.0 || ^5.0.0 | 否 |
未安装 Vue Router 时,onLoad 默认收到空对象;浏览器标签页切回前台时无法按当前路由过滤组件。
导入
直接使用子包:
import { onLoad, onShow } from '@gitlon/hooks'通过主包使用:
import { onLoad, onShow } from 'gitlon'快速开始
<script setup lang="ts">
import { onLoad, onShow } from '@gitlon/hooks'
onLoad((query) => {
// /detail?id=1&from=list
// query: { id: '1', from: 'list' }
console.log('页面参数', query)
})
onShow(() => {
console.log('页面显示')
})
</script>Hooks 必须在组件 setup() 或 <script setup> 中同步调用。
生命周期行为
| 场景 | onLoad | onShow |
| --- | --- | --- |
| 组件首次挂载 | 触发一次 | 触发一次 |
| <keep-alive> 页面失活后再次激活 | 不触发 | 再次触发 |
| 浏览器标签页从后台切回前台 | 不触发 | 当前路由页面触发 |
| 组件卸载后创建新实例 | 新实例触发一次 | 新实例触发一次 |
这里的生命周期跟随调用 Hook 的组件实例。若在子组件中调用,则跟随该子组件挂载、激活和卸载。
onLoad
组件实例首次挂载时触发一次,并接收页面 query。
import { onLoad } from '@gitlon/hooks'
onLoad((query) => {
const id = query?.id
console.log(id)
})签名:
type PageQuery = Record<string, string>
type OnLoadCallback = (query?: PageQuery) => void
function onLoad(hook: OnLoadCallback): void默认 query 来源
安装 Vue Router 后,默认读取当前组件实例的 $route.query:
/detail?id=1&tag=a&tag=b转换结果:
{
id: '1',
tag: 'a,b',
}转换规则:
- 所有值转为字符串;
- 数组值过滤
null、undefined后以逗号连接; null、undefined字段被忽略;- 没有路由或 query 时返回
{}。
配合 <keep-alive> 时,页面重新激活不会重复执行 onLoad。
onShow
页面首次挂载、keep-alive 重新激活、浏览器标签页重新可见时触发。
import { onShow } from '@gitlon/hooks'
onShow(() => {
refreshPageData()
})签名:
type OnShowCallback = () => void
function onShow(hook: OnShowCallback): void可以注册多个回调:
onShow(() => refreshUser())
onShow(() => refreshMessages())每次调用都会为当前组件注册独立生命周期回调。
浏览器标签页恢复
当 document.visibilityState 变为 visible 时:
- 使用 Vue Router:只触发当前路由页面对应组件的回调;
- 未使用 Vue Router:无法判断当前页面,已注册组件均按可见处理;
- 组件卸载时自动移除监听。
<keep-alive>
若要获得“页面切走后再回来,只触发 onShow”的行为,应缓存路由页面实例:
<template>
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" />
</keep-alive>
</router-view>
</template>不使用 <keep-alive> 时,路由页面切走后通常被卸载。再次进入会创建新实例,因此 onLoad、onShow 都会再次执行。
Vue 插件
Hooks 无需安装插件即可使用。只有需要自定义 onLoad query 来源时,才需安装 GitlonHooks:
import { createApp } from 'vue'
import { GitlonHooks } from '@gitlon/hooks'
import App from './App.vue'
const app = createApp(App)
app.use(GitlonHooks, {
getQuery: () => ({
source: 'custom',
tenantId: '1001',
}),
})
app.mount('#app')默认导出与 GitlonHooks 相同:
import GitlonHooks from '@gitlon/hooks'从聚合包使用:
import GitlonHooks, { onLoad, onShow } from 'gitlon'插件签名:
interface GitlonHooksOptions {
getQuery?: () => PageQuery | undefined
}
const GitlonHooks: {
install(app: App, options?: GitlonHooksOptions): void
}设置 getQuery 后,其返回值优先于 $route.query。返回 undefined 时,onLoad 回调也会收到 undefined,不会回退到路由 query。
类型
export type PageQuery = Record<string, string>
export type OnLoadCallback = (query?: PageQuery) => void
export type OnShowCallback = () => void
export interface GitlonHooksOptions {
getQuery?: () => PageQuery | undefined
}类型导入:
import type {
GitlonHooksOptions,
OnLoadCallback,
OnShowCallback,
PageQuery,
} from '@gitlon/hooks'通过主包导入:
import type { GitlonHooksOptions, PageQuery } from 'gitlon'TypeScript 示例
<script setup lang="ts">
import { onLoad, onShow, type PageQuery } from '@gitlon/hooks'
interface DetailQuery extends PageQuery {
id: string
}
onLoad((query) => {
const detailQuery = query as DetailQuery | undefined
if (!detailQuery?.id) return
loadDetail(detailQuery.id)
})
onShow(() => {
trackPageVisible()
})
</script>PageQuery 只能表达字符串字典,不负责保证必填字段存在。具体页面参数仍应由页面自行判断或校验。
SSR
服务端渲染环境中:
- 不访问不存在的
document; - 不注册
visibilitychange; - Vue 挂载生命周期不会在服务端执行,因此回调不会触发。
注意事项
- 必须在
setup()或<script setup>中同步调用。 - 在 setup 外调用会输出警告,不会注册回调。
onLoad是组件实例首次挂载语义,不是全局路由首次访问语义。onShow是组件显示语义;在子组件中使用时跟随子组件生命周期。- 自定义
getQuery应直接返回最终的Record<string, string>。
