UI工具之Storybook

Overview

今天科普一個有趣的前端開源工具——Stroybook,一個 UI 的可視化容器,可以視作組件庫的 wiki。

Storybook is an open source tool for developing UI components in isolation for React, Vue, and Angular. It makes building stunning UIs organized and efficient.

效果如下所示:左側組件導航;右側是組件細節,還可以做一些可視化操作。

Story

基本用法

我這里以 VUE 項目為例,簡單介紹一下如何在項目里集成 storybook。
官方給出了一個極簡的集成方法,只要在根目錄的命令行敲下如下一行就行了。(本文結束)

npx -p @storybook/cli sb init --type vue

如上自動化集成方式太過精簡,讓人不知所措,所以我還是介紹一下手工集成的方式。

添加依賴

先在 devDependencies 里添加@storybook

yarn add @storybook/vue -D

官方文檔里還會要求我們添加許多額外的依賴,但是現代的 vue 項目基本是用 vue-cli 腳手架生成的,它已經添加了足夠多的 dev 依賴。一般來說是 storybook 的服務已經可以直接啟動了的,當然之后顯示失敗的話也會提示你缺少了某幾個依賴,大家可以根據提示添加依賴。 babel-preset-vue是最高頻的缺失,可能是這個庫好多年沒更新了,現在的腳手架已經把它忘了。如果確實沒有,就照例添加即可。

yarn add babel-preset-vue -D

創建 config.js 文件

storybook 自然也有配置文件,我們在根目錄里建一個.storybook/config.js文件。這里吐槽一下前端的配置文件,實在是太多太多了,根目錄里基本全是這類東西了。多到我們組里開發了一年多的小朋友,還沒認清所有。

然后在該配置文件里寫上如下內容:

// .storybook/config.js
import { configure } from '@storybook/vue';

configure(require.context('../src/components', true, /\.stories\.js$/), module);

配置挺直白的,就是讓 storybook 服務找到src/components文件夾下所有.stories.js結尾的文件。這里的每一個 story,都會指向一個 vue component,就把它當做該組件的說明即可。

寫一個組件

我們在 src/components 下寫一個自己的組件——MyButton.vue

<!- MyButton.vue ->
<template>
    <button class="button-style" @click="onClick">
        <slot></slot>
    </button>
</template>

<script>
export default {
    name: 'my-button',
    methods: {
    onClick() {
      console.log('Hello World!');
    },
  },
}
</script>

<style scoped>
.button-style {
    border-radius: 35% 10%;
    color: #FFF;
    background-color: #00bcd4;
    font-size: 2em;
    line-height: 1.2em;
    margin: 1em 1em;
    cursor: pointer;
}
</style>

組件很簡單,就是封裝了原生 button tag:加了點樣式,并且當點擊它時控制臺能打出Hello World!

編寫 stories

stories 其實可以隨意放置,我這里就 follow 項目里 jest 的風格,把 stories 也放在了組件旁邊。

src/components
 ├── MyButton.vue
 ├── MyButton.stories.js
 └── MyButton.spec.js

@story/vue,其實就是在 js 文件里寫了個無狀態的 vue 組件,寫法也很簡單:引用組件,注冊組件,模版封裝。結束!

// MyButton.stories.js
import MyButton from './MyButton.vue';

export default { title: 'My-Button' };

export const Component = () => ({
    components: { MyButton },
    template: '<my-button>my button</my-button>'
  });

運行 storybook

Storybook 的服務其實就是 webpack-dev-server,開發時可以熱加載,很方便編寫 stories 和 vue 組件本身。我們給服務設置個端口,比如 6006,開始運行:

yarn start-storybook -p 6006

不出意外的話,chrome 會自己打開localhost:6006。瀏覽器如下所示。左側列出了組件導航,名字就是MyButton.stories.jstitle;右側是真實組件的樣式,點擊后,@click事件觸發,打印出Hello World!

My Button

如果你想打包成靜態資源發布,也很容易:

yarn build-storybook

默認會在根目錄會創建一個.out文件夾,里面就是所有靜態資源了。

插件系統

主線劇情就到此為止了,但是 storybook 遠不止于此,它自帶一種叫 addon 的插件系統。(不要問我,addon 和 plugin 的區別)。

我們可以自己寫一個簡單的 addon, 比如顯示組件父親的 border。
還記得上面的.storybook/config.js文件嗎?我們的 addon 就是在里面調用addDecorator,給所有的 story 包一層div,并顯示 border:

//.storybook/config.js

import { configure, addDecorator } from '@storybook/vue';

configure(require.context('../src/components', true, /\.stories\.js$/), module);

addDecorator(() => ({
    template:`
      <div style="border:solid;">
        <story/>
      </div>`
  }))

看一下結果,border 顯示出來了。

Parent Border

當然上面只是一個示例,現實意義不大,我自己組里開發的時候用到 vuetify,所以一般都會給所有控件包一層<v-app></v-app>,不然可能顯現不出 v 組件效果來。

更多的時候,我們是直接集成社區里提供的 addon,比如@storybook/addon-knobs——用于調試 vue 的動態變量。

還是一步一步來,先裝個依賴:

yarn add @storybook/addon-knobs -D

接著在.storybook文件夾下創建addons.js文件,并引入依賴

// .storybook/addons.js
import '@storybook/addon-knobs/register';

然后啟動服務,看到沒?下面多了個Knobs的 tab:

Knobs

之后把 knobs 添加到每一個 story 就可以了。我們稍許修改一下代碼,通過storiesOf形式注冊 story:

// MyButton.sotries.js
import { storiesOf } from '@storybook/vue';
import { withKnobs, text } from '@storybook/addon-knobs';

import MyButton from './MyButton.vue';

const components = () => ({
  components: { MyButton },
  props: {
    text: {
      default: text('Text', 'my button')
    }
  },
  template: `<MyButton>{{ text }}</MyButton>`
})

storiesOf('My-Button')
.add('components', components)
.addDecorator(withKnobs);

Knobs 根據 story 的 props 生成 mock 數據,并雙向綁定對象組件的變量,效果如下:

Knobs Button

小結

這期科普了一個比較有趣的開發工具——Storybook,它可以很方便地幫助我們組織基礎 UI 控件。不同的前端開發可以通過很直觀的方式復用對方的組件,以期減少冗余代碼。此外,我個人覺得編寫 Story——可視化組件的最大意義還是在于可測試;我們組之前的組件業務侵入太重,組件本身很難編寫單元測試,因此前端的測試覆蓋率一直非常低。現在想想,可能是我們本身就寫錯組件了,組件并非頁面,應該能獨立展示,不該包含太多業務。我現在在項目里強制加入 Storybook 也是希望能改善之前的困局。

相關

文章同步發布于an-Onion的Github。碼字不易,歡迎點贊。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 安裝vue腳手架: Node.js>=8.9沒有vue-cli3的先安裝一下: 安裝完后查看版本: 創建項目: 選...
    helloyoucan閱讀 10,745評論 0 7
  • 前言 最近掐指一算發現本月還有篇技術博文沒寫~,雖然隨便拿一篇日常積累的文章,或者把最近重構的一些點拿出來講都可以...
    臨水照影233閱讀 12,016評論 0 7
  • 基于Vue的一些資料 內容 UI組件 開發框架 實用庫 服務端 輔助工具 應用實例 Demo示例 element★...
    嘗了又嘗閱讀 1,175評論 0 1
  • 原文鏈接對于一名前端開發者,必須面對的就是組件化開發。我做Angular開發已經有些日子了,也曾為自己的項目開發過...
    Laura_hu閱讀 10,365評論 0 4
  • 目錄 第一章 介紹第二章 設計機制第三章 JNI類型和數據結構第四章 JNI函數(1)第四章 JNI函數(2)第四...
    駱駝騎士閱讀 7,052評論 0 58