npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

vue-page-controller

v0.0.5-beta7

Published

**解决问题** * 页面前进(暂存、创建)、后退(销毁、复用)、替换时,组件实例能按栈数据结构做创建、销毁 * keep-alive 组件复用为堆数据结构,且只能按组件复用 * vue-router 页面之间无法传递对象及函数参数

Downloads

3

Readme

page-controller

解决问题

  • 页面前进(暂存、创建)、后退(销毁、复用)、替换时,组件实例能按栈数据结构做创建、销毁
  • keep-alive 组件复用为堆数据结构,且只能按组件复用
  • vue-router 页面之间无法传递对象及函数参数

注意事项

  • 仅支持vue3
  • 路由功能相比vue-router,不支持正则匹配、别名, 不支持路由嵌套

数据结构说明

页面配置

页面路由定义时配置信息

type PageConfig = {
  // 页面名称
  name: string
  // 页面显示路径
  path: string
  // 页面重定向
  redirect?: PageRedirect
  // 页面组件
  component?: Component | DefineComponent | Promise<Component | DefineComponent>
  // 页面其他信息
  meta?: Record<string, any>
}

页面信息

页面加载或路由钩子方法

type PageInfo<T = Record<any, any>> = {
  name: string
  path: string
  // query参数在hash模式会显示在url中
  query: Record<string, string | undefined>
  // 任意类型
  params?: T
}

页面路由钩子

interface PageHooks {
  /**
   * 页面创建之前,没有页面实例
   */
  beforePageEnter?: OptionConfig<BeforePageEnterOption>
  /**
   * 页面移除之前,有页面实例
   */
  beforePageLeave?: OptionConfig<BeforePageLeaveOption>
  /**
   * 页面进入后台之前,有页面实例
   */
  beforePageBackend?: OptionConfig<BeforePageBackendOption>
  /**
   * 页面进入前台之前,有页面实例(hash模式,当页面刷新后,再做后退操作时,会执行beforePageEnter钩子)
   */
  beforePageFrontend?: OptionConfig<BeforePageFrontendOption>
  /**
   * 页面改变触发事件
   * @param params
   */
  onPageChange?: (
    params: OptionConfigParams & {
      type: PageActionType
    }
  ) => void
}

页面控制模式

页面路由控制的两种模式,Hash模式渲染页面和浏览器的记录会双向关联;Memory模式,只会在当前内存保存,页面刷新路由状态丢失

enum HistoryType {
  // url hash模式
  Hash,
  // 内存模式
  Memory
}

设计说明

就部分关键功能做说明

  • 如何标记组件实例的唯一标识

    当push、replace创建一条路由记录时,生成唯一标识保存到路由query参数中,以此作为当前路由及渲染组件实例的唯一标识

  • 如何实现页面栈管理

    此处分为了两部分:页面路由信息栈、组件实例栈

    其中页面路由信息栈使用数组维护

    为避免使用Vue3私有api,保证版本兼容性,使用keep-alive,通过动态生成组件,完成组件实例栈管理

    此处利用keep-alive 的include参数控制哪些组件实例需要被缓存

    根据路由信息栈发生改变时,生成 include 参数供 keep-alive 使用,同时根据栈顶路由信息动态生成对应组件,组件名称与 include 参数一致

    如此可达到,页面路由信息栈、组件实例栈一致的目的

  • 如何实现url hash 与渲染页面联动

    路由控制器的方法(push、pop、replace)触发跳转时,通过浏览器 history 更新对应 status 记录(当前、之前、之后 页面标识)和

    当前浏览器hash变化时,监听 popstate 事件,在 status 的当前页面标识和根据当前hash得到的页面标识不一致时,触发push、pop操作

  • 如何实现hash模式页面刷新防参数丢失

    url hash模式,路由变化时,使用sessionStorage保存页面路由信息栈的序列化信息,当页面控制器初始化时,首先加载sessionStorage反序列化后的信息

  • 代码设计说明

code-design.png

渲染页面生命周期

  • push 当前页面组件实例进入后台,根据路由信息创建组件入栈并激活
  • pop 当前页面组件实例销毁出栈,栈顶页面组件实例再次激活
  • replace 当前页面组件实例销毁出栈,根据路由信息创建组件入栈并激活

当url hash模式刷新浏览器

session 路由记录存在

  • pop 当前页面组件出栈,无法找到栈顶页面组件实例,只能根据栈顶页面信息重新创建

session 路由记录不存在

浏览器前进、后退及pop操作触发的页面 push、pop,均会转换为replace操作(可能为多步前进后退,无法维护页面栈状态)

life-cycle.png

如何使用

路由定义

import { createPageController } from 'vue-page-controller'
const pageController = createPageController({
  // 可选参数, 路由query参数添加的key
  pageIdKey: 'pid',
  // 页面打开,默认加载的路由
  defaultName: 'root',
  // 路由定义
  pageConfigs: [
    {
      name: 'root',
      path: '/',
      component: PageList
    },
    {
      name: 'list',
      path: '/list',
      component: PageList
    },
    {
      name: 'detail',
      path: '/detail',
      component: () => import('./components/Detail.vue')
    }
  ]
})

当需要改变query参数中页面id的key,可自定义pageIdKey 参数

注意

  • 当使用url hash模式时,需要在vue初始化时使用createPageController创建控制器,并使用app.use全局挂载。

    一个app最多只能有一个url hash模式的路由控制器

    const app = createApp(App)
    app.use(pageController)
  • 当使用Memory模式时需要在setup 函数中创建控制器

路由入口

页面控制器入口组件为 PageController

import { PageController } from 'vue-page-controller'
  1. url hash模式使用全局配置控制器,组件内无需传入, 另外app.use(pageController)会自动全局使用组件,页面内直接使用即可
    <page-controller />
  2. 内存模式时需要手动引用组件,同时创建路由控制器传入
    import { PageController } from 'vue-page-controller'
    export default defineComponent({
        components: {
          PageController
        }
    })
       
    <page-controller :controller="pageController" />

路由跳转

  1. push 打开新页面

    路由跳转参数中name、path至少有其中一个

    const { pageController } = usePageController()
       
    // 使用name
    pageController.push({
      name: 'detail'
    })
       
    // 使用path
    pageController.push({
      path: '/detail'
    })
       
    // 使用query或params参数,其区别,可看数据结构PageInfo中说明
    pageController.push({
      name: 'detail',
      params: {
        info: {
          title: 'xxx'
        },
        callback: (res) => {}
      },
      query: {
        name: 'xxx'
      }
    })

    备注: url hash模式页面刷新,当前页面params参数中有函数等不可序列化的参数时,函数等内容会丢失(不可序列化内容无法保存)

  2. pop 页面后退

    const { pageController } = usePageController()
    // 路由页面实例出栈
    pageController.pop()
    // 路由页面后退
    pageController.back()

    pop、back 方法区别:

    • pop方法,在路由栈记录为1时,不做任何操作
    • 当为内存模式时,back即为pop方法
    • 当为url hash模式时,back为浏览器history的back方法

    建议使用back方法做后退操作,避免session路由记录信息丢失时无法后退

  3. replace 替换当前页面 方法名称变化,参数信息同push

转场动画

PageController 组件内置了转场动画参数 animation,开启后内部会使用Transition组件, 根据页面不同跳转方式,再页面跳转前使用不同的Transition动态过渡参数,不同跳转方式参数名称如下:

  • push:page-push
  • pop:page-pop
  • replace:page-replace

例如:

transition.gif

全局引入一下css样式,具体转场效果可按需调整,Transition转场样式

.page-push-enter-active,
.page-push-leave-active,
.page-pop-enter-active,
.page-pop-leave-active {
  transition: all 300ms ease-in-out;
}
.page-replace-enter-active {
  transition: all 300ms ease-out;
}
.page-replace-leave-active {
  transition: all 300ms ease-in;
}

.page-push-enter-from {
  opacity: 0.5;
  transform: translate3d(100%, 0, 0);
}
.page-push-leave-to {
  opacity: 0.5;
  transform: translate3d(-100%, 0, 0);
}

.page-pop-enter-from {
  opacity: 0.5;
  transform: translate3d(-100%, 0, 0);
}

.page-pop-leave-to {
  opacity: 0.5;
  transform: translate3d(100%, 0, 0);
}

.page-replace-enter-from,
.page-replace-leave-to {
  opacity: 0;
}

路由钩子

hooks.png

在页面跳转过程中,其触发时机如上图所示(均为页面B所涉及的钩子函数),共有5个钩子函数。

  1. beforePageEnter 页面组件创建
  2. beforePageLeave 页面组件销毁
  3. beforePageBackend 页面组件进入后台
  4. beforePageFrontend 页面组件进入前台
  5. onPageChange 只要页面发生切换即会触发,以上4个钩子函数触发时必然伴随该钩子触发

5个钩子函数均可为异步函数,异步函数等待时会阻塞当前跳转行为,若期间有其他路由跳转变栈顶页面,则等待结束当前跳转行为取消

onPageChange 仅做通知,不会影响当前路由的行为,其余4个钩子,均能阻断当前路由的行为(返回值为false)

全局钩子函数定义

通过创建的页面控制器设置

pageController.beforeEach({
  async beforePageEnter(options: BeforePageEnterOption) {
    const notBreak = options.to.params?.idx !== 2
    return notBreak
  },
  beforePageBackend(options: BeforePageBackendOption) {},
  beforePageFrontend(options: BeforePageFrontendOption) {},
  beforePageLeave(options: BeforePageLeaveOption) {},
  onPageChange(options: OnPageFrontendOption) {}
})

页面内钩子函数设置

  • 选项式api

    各钩子函数均可设置

    export default defineComponent({
      name: 'xxx',
      setup() {
        return {}
      },
      beforePageEnter(options: BeforePageEnterOption) {},
      beforePageBackend(options: BeforePageBackendOption) {},
      beforePageFrontend(options: BeforePageFrontendOption) {},
      beforePageLeave(options: BeforePageLeaveOption) {},
      onPageChange(options: OnPageFrontendOption) {}
    })
  • 组合式api

    仅能设置除beforePageEnter之外的钩子函数

      export default defineComponent({
        name: 'xxx',
        setup() {
          const { usePageBeforeEach } = usePageController()
          usePageBeforeEach({
            beforePageBackend: (options: BeforePageBackendOption) => {},
            beforePageFrontend: (options: BeforePageFrontendOption) => {},
            beforePageLeave: (options: BeforePageLeaveOption) => {},
            onPageChange: (options: OnPageFrontendOption) => {}
          })
          return {}
        },
      })

备注

当url hash模式刷新浏览器,页面再做pop操作时,没有组件实例beforePageFrontend不会触发,而是重新生成组件实例,触发beforePageEnter

钩子函数执行优先级

  • (beforePageLeave、beforePageBackend) > (beforePageEnter、beforePageFrontend) > onPageChange
  • 组合式api > 选项式api > 全局设置钩子
  • 同一类型 先设置 > 后设置

其他

具体使用示例可查看demo应用,如有功能bug请及时反馈