Vue 3 路由器

一个 Storybook 装饰器,允许您为路由感知组件构建故事。

在 Github 上查看

Storybook Vue3 路由器

minified + gzip size Npm package monthly downloads Release CodeFactor Storybook

一个 Storybook 装饰器,允许您使用 Vue 3 路由感知组件。

如果您想使用 <router-view><router-link> 为 Vue 3 组件构建故事,那么您需要使用 vue-router 来包装您的故事,这个附加组件将允许您轻松地做到这一点。

还提供了一个 模拟路由器装饰器 选项,供只需要访问 $route$router 属性的用户使用。

如何使用

此装饰器与 Storybook 的 组件故事格式 (CSF)悬挂的 CSF 注释 协同工作,这是从 Storybook 6 开始推荐的编写故事的方式。它还没有在 storiesOf API 中进行测试。

Storybook v6:请使用包版本 2.x

Storybook v7:请使用包版本 3+

请参阅 迁移指南

安装装饰器

npm install --save-dev storybook-vue3-router
// or
yarn add --dev storybook-vue3-router

在您的故事中使用

默认设置将创建一个 vue-router 实例,包含 2 个路由(//about)- 这些可以在 defaultRoutes.ts 文件中进行查看。

/* import storybook-vue3-router */
import { vueRouter } from 'storybook-vue3-router'

/* ...story setup... */

/* your story export */
export const Default = Template.bind({})

/* adding storybook-vue3-router decorator */
Default.decorators = [
  /* this is the basic setup with no params passed to the decorator */
  vueRouter()
]

演示

您可以在 示例故事 中看到发布在这个 演示 上。

高级用法

此装饰器带有可选参数,用于自定义 Storybook 中 vue-router 的实现。

自定义路由

/* define our custom routes */
const customRoutes = [
  {
    path: '/',
    name: 'home',
    component: HomeComponent // this would need to be defined/imported into the `.stories` file
  },
  {
    path: '/about',
    name: 'about',
    component: AboutComponent // this would need to be defined/imported into the `.stories` file
  }
]

/* adding storybook-vue3-router decorator */
Default.decorators = [
  /* pass custom routes to the decorator */
  vueRouter(customRoutes)
]

自定义路由(带守卫)

/* define our custom routes */
const customRoutes = [
  // ...
  {
    path: '/admin',
    name: 'admin',
    component: AdminComponent,
    /* add per-route navigation guard */
    beforeEnter: (to, from, next) => {
      // ...
    }
  }
]

/* adding storybook-vue3-router decorator */
Default.decorators = [
  /* pass custom routes to the decorator */
  vueRouter(customRoutes)
]

自定义路由(带初始路由)

默认情况下,装饰器会将起始路由默认为 /,如果要更改它,可以将其作为参数传递给装饰器。

/* define our custom routes */
const customRoutes = [
  {
    path: '/',
    name: 'dashboard',
    component: Dashboard
  },
  {
    path: '/intro',
    name: 'intro',
    component: Intro
  }
]

### With Router Options
We can pass [Vue Router options](https://router.vuejs.ac.cn/api/index.html#history) into our decorator.

```typescript
/* adding storybook-vue3-router decorator */
Default.decorators = [
  /* pass vueRouterOptions to the decorator */
  vueRouter(undefined, {
    vueRouterOptions: {
      linkActiveClass: 'my-active-class',
      linkExactActiveClass: 'my-exact-active-class'
      ...etc
    }
  })
]

router.isReady()

如果您使用 router.isReady() 设置了路由,或者您有在创建生命周期钩子中需要特定路由/路由数据的组件,您可能需要使用 asyncVueRouter 导出。

此导出提供了路由器,该路由器在路由器准备好之前不会渲染故事。

故事设置

import { asyncVueRouter } from 'storybook-vue3-router'

/* define our custom routes */
const customRoutes = [
  {
    path: '/',
    name: 'dashboard',
    component: Dashboard
  },
  {
    path: '/intro',
    name: 'intro',
    component: Intro
  }
]

/* adding storybook-vue3-router decorator */
Default.decorators = [
  /* pass initialRoute to the decorator */
  asyncVueRouter(customRoutes, {
    initialRoute: '/intro'
  })
]

Preview.js 异步设置

为了使用 async 路由设置方法,您需要修改您的 .storybook/preview.js 文件,以将故事包装在 Vue 3 的 <Suspense> 组件中。这是因为装饰器需要一个 async setup() 来正确地 await router.isReady()。您可以将预览修改为

const preview = {
  decorators: [
    (story) => ({
      components: { story },
      template: '<Suspense><story /></Suspense>',
    }),
  ],
};

export default preview;

请参阅 示例文件夹,以了解更高级的用法。

装饰器参数


function vueRouter(routes: RouteRecordRaw[], options?: { initialRoute?: string, beforeEach?: NavigationGuard, vueRouterOptions?: RouterOptions })
function asyncVueRouter(routes: RouteRecordRaw[], options?: { initialRoute?: string, beforeEach?: NavigationGuard, vueRouterOptions?: RouterOptions })

模拟路由器

并不总是需要完整的 vue-router- 例如,如果您没有使用 <router-view><router-link> 的组件,那么使用 mockRouter 导出可能会满足您的需求(并减少故事中使用的导入)。

注意:mockRouter 仅在使用选项 API this.$route 和/或 this.$router 的情况下有效,它不适用于使用 vue 路由器组合式 API(如 useRoute()useRouter())的用例。

在您的故事中使用 mockRouter

默认设置将从 vue-router 创建模拟 $router$route,这允许您为使用编程导航和基于路由的逻辑的组件创建故事。

我们还可以将自定义选项传递到 mockRouter 装饰器中。

{ 
  meta?: Array<string>, 
  params?: Array<string>, 
  query?: Array<string>
}
/* import storybook-vue3-router mockRouter */
import { mockRouter } from 'storybook-vue3-router'

/* ...story setup... */

/* your story export */
export const Default = Template.bind({})

/* adding storybook-vue3-router mockRouter decorator */
Default.decorators = [
  mockRouter({
    meta: ['some_meta'],
    params: ['some_param'],
    query: ['some_query']
  })
]

您可以在我们的 storybook 演示站点 和我们的 代码示例 中看到 mockRouter 的示例。

v2.x > v3+ 迁移

⚠️ 重大更改 ⚠️

v3.x 版本不再使用 vueRouter 装饰器的默认导出,您需要更新为使用命名导入。

/* DONT */
import vueRouter from 'storybook-vue3-router'
/* DO */
import { vueRouter } from 'storybook-vue3-router'

v1.x > v2.x 迁移

从 v1 迁移带来了一些重大更改。

// v1.x - 2nd param is used to pass `beforeEach` router guard
// in this example the guard is used to fire a storybook action with `to` and `from` router objects
vueRouter(customRoutes, (to, from) => action('ROUTE CHANGED')({ to: to, from: from })) // LEGACY

// v2.1 - 2nd param is used to pass additional options to the decorator
vueRouter(customRoutes, {
  /* add global beforeEach guard */
  beforeEach: (to, from) => action('ROUTE CHANGED')({ to: to, from: from })
})

如果您之前在第二个参数中使用 v1 与路由守卫,则需要将这些守卫重构为使用 特定于路由的路由守卫(推荐),或者您可以使用 beforeEach 选项传递全局路由守卫。

v2.0 没有此 beforeEach 选项,请升级到 v2.1。

⚠️ 警告

使用全局 beforeEach 选项时,如果存在另一个也使用此装饰器的故事,那么我们必须强制页面重新加载,以便设置特定故事路由守卫,这对用户体验/性能有轻微影响。查看 演示,以了解此示例:README > 带有路由守卫 > 全局守卫 - 当您单击“全局守卫”链接时,您会注意到页面已刷新以应用全局守卫(由于之前存在的故事)。

如果您只为一个故事使用此装饰器,则不会出现此问题。

在解决 此问题 后,为了能够使用不同的路由设置创建多个故事,人们注意到这会导致在每个路由上添加全局 beforeEach 函数。例如,每次单击不同的故事时,都会添加新的 beforeEach 钩子 - 但之前的钩子不会被删除,这会导致在与“活动”故事无关的故事上触发多个守卫。

由以下人员制作
  • nickmcburney
    nickmcburney
与以下内容一起使用
    Vue
标签