加入直播:周四,东部夏令时 11 点,Storybook 9 发布 & AMA
返回集成
vuetify

集成Vuetify与 Storybook

Vuetify 是一个基于 Vue 的组件库,设计遵循 Google 的 Material Design 规范。
前提条件

本秘籍假定你已拥有使用 Vuetify v3 的 Vue 3 应用,并已使用入门指南设置好 Storybook 7.0 或更高版本。没有这些?遵循 Vuetify 的安装说明,然后运行

# Add Storybook:
npm create storybook@latest

1. 在 Storybook 中注册 Vuetify

首先,你需要将 Vuetify 的字体加载器和插件添加到你的 Storybook 配置中。为此,将以下内容添加到你的 .storybook/preview.js 文件中

// .storybook/preview.js
 
import { setup } from '@storybook/vue3';
import { registerPlugins } from '../src/plugins';
 
setup((app) => {
  // Registers your app's plugins into Storybook
  registerPlugins(app);
});

在这里,registerPlugins 会加载 Vuetify 的字体,并将所有组件注册到 Storybook 的 Vue 应用中。

2. 创建一个故事包装组件

接下来,你需要用 Vuetify 的 v-app 组件包裹你的故事,以便使用其一些大型布局组件,例如 v-app-bar。为此,在 .storybook/ 目录中创建一个名为 StoryWrapper.vue 的组件。

<!-- .storybook/StoryWrapper.vue -->
 
<template>
  <v-app>
    <v-main>
      <slot name="story"></slot>
    </v-main>
  </v-app>
</template>
 
<script></script>

3. 创建一个 withVuetifyTheme 装饰器

现在创建一个 Storybook 装饰器,用它来将你的故事包裹在 StoryWrapper 组件中。

下面我在 .storybook 目录中创建了一个新文件,名为 withVuetifyTheme.decorator.js

// .storybook/withVeutifyTheme.decorator.js
 
import { h } from 'vue';
import StoryWrapper from './StoryWrapper.vue';
 
export const withVuetifyTheme = (storyFn, context) => {
  const story = storyFn();
 
  return () => {
    return h(
      StoryWrapper,
      {}, // Props for StoryWrapper
      {
        // Puts your story into StoryWrapper's "story" slot with your story args
        story: () => h(story, { ...context.args }),
      }
    );
  };
};

现在,在你的 preview.js 文件中将此装饰器提供给 Storybook。

// .storybook/preview.js
 
import { setup } from '@storybook/vue3';
import { registerPlugins } from '../src/plugins';
import { withVuetifyTheme } from './withVuetifyTheme.decorator';
 
setup((app) => {
  registerPlugins(app);
});
 
/* snipped for brevity */
 
export const decorators = [withVuetifyTheme];

4. 添加一个主题切换工具

Vuetify 自带浅色和深色主题,你可以覆盖它们或添加新主题。为了充分利用你的故事,你应该有一个在所有主题之间切换的方式。

要添加我们的切换器,请在 .storybook/preview.js 文件中声明一个名为 theme全局类型,并为其指定一个支持的主题列表供选择。

// .storybook/preview.js
 
export const globalTypes = {
  theme: {
    name: 'Theme',
    description: 'Global theme for components',
    toolbar: {
      icon: 'paintbrush',
      // Array of plain string values or MenuItem shape
      items: [
        { value: 'light', title: 'Light', left: '🌞' },
        { value: 'dark', title: 'Dark', left: '🌛' },
      ],
      // Change title based on selected value
      dynamicTitle: true,
    },
  },
};

这段代码将在工具栏中创建一个新菜单,用于为你的故事选择所需的主题。

5. 添加一个主题提供者

需要有一种方法告知 Vuetify 使用工具栏中选定的主题。这可以通过更新我们的 StoryWrapper 组件和 withVuetifyTheme 装饰器来实现。

首先,给 StoryWrapper 组件一个 themeName prop,该 prop 可以传递给 v-app 组件。

<template>
  <v-app :theme="themeName">
    <v-main>
      <slot name="story"></slot>
    </v-main>
  </v-app>
</template>
 
<script>
export default {
  props: {
    themeName: String,
  },
};
</script>

现在,通过我们的装饰器,将我们的全局 theme 变量作为 prop 传递给我们的 StoryWrapper 组件。

// .storybook/withVeutifyTheme.decorator.js
 
import { h } from 'vue';
import StoryWrapper from './StoryWrapper.vue';
 
export const DEFAULT_THEME = 'light';
 
export const withVuetifyTheme = (storyFn, context) => {
  // Pull our global theme variable, fallback to DEFAULT_THEME
  const themeName = context.globals.theme || DEFAULT_THEME;
  const story = storyFn();
 
  return () => {
    return h(
      StoryWrapper,
      // give themeName to StoryWrapper as a prop
      { themeName },
      {
        story: () => h(story, { ...context.args }),
      }
    );
  };
};

参与贡献

现在你已经准备好在 Storybook 中使用 Vuetify 了。🎉 查看示例仓库以便快速开始。

如果你在工作中使用 Vuetify,我们很希望能得到你的帮助来制作一个插件,它能自动应用上述配置。加入 Discord 与维护者交流并参与贡献,或者直接阅读插件文档

标签
贡献者
  • ShaunEvening
    ShaunEvening