返回博客

在 Storybook 中构建页面

为难以触及的页面状态编写故事

loading
Kyle Gach
@kylegach
最后更新

虽然在应用中构建页面看似简单,但随着项目的发展,情况会变得更加复杂。如果网络失败或数据丢失怎么办?更糟糕的是,您的应用收到格式错误或不完整的数据。在所有这些情况下,页面应该渲染什么?

Mozilla、The Guardian 和 Shopify 的领导团队使用 Storybook 来捕获难以重现的页面状态。这有助于他们有条理地处理用户可能遇到的每种情况。

本文展示了如何使用 Storybook 来隔离开发页面。我们将使用组件百科——一个新网站,用于编目世界上 UI 组件供前端开发人员参考。它由数百个页面组成,涵盖了各种 UI 状态和数据变体。

Three examples of the Project Detail page, for Adobe Spectrum Design System, Monday.com Vibe Design System, and The Guardian Web
每个页面都根据可用数据进行了定制

为什么使用 Storybook 构建页面?

页面具有非显而易见的要求,例如布局、可访问性、设备兼容性、性能和用户个性化。这为前端开发人员带来了无数需要构建和维护的状态。

Storybook 帮助您隔离构建每个页面状态,然后将其保存为故事,以便在 QA 和自动化测试期间进行重新访问。

💎 捕获边缘情况
故事展示了您页面的各种状态。这包括在您的应用程序中难以触及的边缘情况,例如加载状态和空状态。

🖼 分享您的作品
通过发布您的 Storybook,您可以与团队共享特定状态下特定故事的链接以获取反馈。这简化了审批流程。

✅ 测试用户交互
即使是最简单的任务,用户也需要跨页面上的多个组件完成一系列步骤。您可以通过编写用户行为脚本并在 play 函数中编写断言来验证这些交互。

如何在 Storybook 中构建页面

页面实际上只是一个具有额外数据要求的组件。它的构建方式与普通组件类似。首先,在数据齐全的最常见“默认”状态下开发页面。然后,为无数据、数据丢失、响应式断点等边缘情况编写故事。

故事帮助您跟踪页面状态

页面的理想状态是所有数据都已提供。我们可以用捕获此状态的输入来编写 Default 故事

Default.args = {
 authorAvatarUrl: mockImageUrl(50, 50),
 componentCount: 55,
 components: mockComponents,
 contributors: [
   {
     avatarUrl: mockImageUrl(50, 50),
     name: 'First Last',
   },
   {
     avatarUrl: mockImageUrl(50, 50),
     name: 'First Last',
   },
   {
     avatarUrl: mockImageUrl(50, 50),
     name: 'First Last',
   },
 ],
 description: 'Spectrum provides components and tools to help product teams work more efficiently, and to make Adobes applications more cohesive',
 downloads: 15123,
 gitHubUrl: '#',
 org: 'Adobe',
 packageName: 'packagename',
 storyCount: 135,
 storybookUrl: '#',
 title: 'Spectrum Design System',
}
The Project Detail page for Adobe Spectrum Design System, in its ideal state, rendered as a story in Storybook

但对于“无数据”状态等不太理想的情况呢?我们可以重用 Default 故事的输入,然后覆盖其中一些值来正确创建该状态

NoComponents.args = {
 ...Default.args,
 componentCount: 0,
 components: []
}
The Project Detail page in a story for the "no components" state

有时,需要通过与页面交互而不是提供输入来演示页面状态。我们可以使用play 函数来模拟交互,例如在筛选控件中输入以检查其行为和结果

Filter.args = {
 ...Default.args
};
Filter.play = async ({ canvasElement }) => {
 const canvas = within(canvasElement);
 const filter = await canvas.findByLabelText('Filter by name');
 
 await userEvent.type(filter, 'But', { delay: 100 });
};
An animation of a story demonstrating the "components filter" functionality
通过交互测试模拟用户行为

将复杂页面分解为简单组件

如果您采用组件驱动的方法,即将 UI 从可重用组件组装起来,您可以通过将页面分解为其组成部分来进一步分解页面。

例如,组件百科中的“项目”页面大部分复杂性都集中在页眉区域。为了将数据加载等页面级关注点与标题长度等组件级关注点分开,我们将页眉提取到一个单独的组件中,并为其编写自己的故事。

Illustration of extracting the header component out of the rest of the page, with text reading "Decompose complex parts of a page into their own component"

使用插件测试行为、可访问性等

一旦我们编写了故事,我们就可以通过插件使我们的 Storybook 更有用。除了演示页面的各种状态外,我们还可以使用a11y 插件检查可访问性,该插件提供了一个方便的检查状态面板,在我们工作时会更新。更进一步,我们可以使用新发布的交互测试在 CI 中将我们的故事作为自动化测试运行。

结论

构建页面是所有开发人员都必须做的事情。在应用程序中构建页面既困难又容易出错,因为许多状态很难重现。您最终会点击用户流程或篡改夹具来处理每个状态。

故事是页面“已知良好状态”的实时文档,您可以与团队共享。您会独立开发每个页面的故事。这使您可以避免棘手的业务逻辑或混乱的应用程序上下文。

本文的灵感来源于我们为组件百科构建页面的努力,该百科收集了公开的 Storybook,其中包含组件和页面供浏览和学习。立即注册 Storybook 邮件列表,以获取组件百科更新和早期访问权限。或者在此处提交您自己的 Storybook 的 URL

加入 Storybook 邮件列表

获取最新消息、更新和发布信息

7,468开发者及更多

我们正在招聘!

加入 Storybook 和 Chromatic 团队。构建被数十万开发人员在生产中使用的工具。远程优先。

查看职位

热门帖子

Storybook 如何帮助设计师和开发人员保持同步

将组件连接到设计规范、文档和反馈
loading
Varun Vachhar

社区案例展示 #1

Figma、SWC、Tensorflow、Spotify 播放列表等
loading
Dominic Nguyen

使用 Storybook 进行交互测试

你编写 Story,Storybook 运行测试
loading
Michael Shilman
加入社区
7,468开发者及更多
原因为什么选择 Storybook组件驱动的 UI
文档指南教程更新日志遥测
社区插件参与进来博客
展示探索项目组件词汇表
开源软件
Storybook - Storybook 中文

特别感谢 Netlify CircleCI