useRouteListener.ts 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. import { onBeforeUnmount } from "vue"
  2. import mitt, { type Handler } from "mitt"
  3. import { type RouteLocationNormalized } from "vue-router"
  4. /** 回调函数的类型 */
  5. type Callback = (route: RouteLocationNormalized) => void
  6. const emitter = mitt()
  7. const key = Symbol("ROUTE_CHANGE")
  8. let latestRoute: RouteLocationNormalized
  9. /** 设置最新的路由信息,触发路由变化事件 */
  10. export const setRouteChange = (to: RouteLocationNormalized) => {
  11. // 触发事件
  12. emitter.emit(key, to)
  13. // 缓存最新的路由信息
  14. latestRoute = to
  15. }
  16. /** 单独监听路由会浪费渲染性能,使用发布订阅模式去进行分发管理 */
  17. export function useRouteListener() {
  18. /** 回调函数集合 */
  19. const callbackList: Callback[] = []
  20. /** 监听路由变化(可以选择立即执行) */
  21. const listenerRouteChange = (callback: Callback, immediate = false) => {
  22. // 缓存回调函数
  23. callbackList.push(callback)
  24. // 监听事件
  25. emitter.on(key, callback as Handler)
  26. // 可以选择立即执行一次回调函数
  27. immediate && latestRoute && callback(latestRoute)
  28. }
  29. /** 移除路由变化事件监听器 */
  30. const removeRouteListener = (callback: Callback) => {
  31. emitter.off(key, callback as Handler)
  32. }
  33. /** 组件销毁前移除监听器 */
  34. onBeforeUnmount(() => {
  35. for (let i = 0; i < callbackList.length; i++) {
  36. removeRouteListener(callbackList[i])
  37. }
  38. })
  39. return { listenerRouteChange, removeRouteListener }
  40. }