Storybookの基本的な記述方法

#Storybookの基本的な記述方法

##Storybookとは
コンポーネント単独で開発ができ、コンポーネントのテストや、色々な状態を設定してコンポーネントの動きをブラウザで確認できる。
また、Storybook自体が納品できる設計書にもなってくれる。

要するに、いちいちページを一個作成しなくても、コンポーネントだけをブラウザで操作して挙動の確認ができる便利なオープンソースのツール。


###Storybookを導入

```
# Vue CLI のインストール
$ npm i -g vue-cli
# プロジェクトディレクトリへ移動
$ cd your-awesome-project
# Vue CLI で webpack-simple テンプレートを使って init 。質問は全部 Enter で OK
$ vue init webpack-simple
# 依存パッケージのインストール
$ npm i
```

Storybook for Vue のセットアップ

```
# Storybook for Vue のインストール
$ npm i -D @storybook/vue
```

package.jsonはこんな感じ

```
"scripts": {
    //xxxxはポート番号
    "storybook": "start-storybook -p xxxx"
}
"devDependencies": {
    ...
    "@storybook/addon-a11y": "^5.1.11",
    "@storybook/addon-actions": "^5.1.11",
    "@storybook/addon-knobs": "^5.1.11",
    "@storybook/addon-links": "^5.1.11",
    "@storybook/addon-notes": "^5.1.11",
    "@storybook/addons": "^5.1.11",
    "@storybook/vue": "^5.1.11",
    ...
  }
 ...
}
```

###vueコンポーネントをstorybookで操作する
src/components/SelectBox.vue

```
<template>
  <select
    :disabled="disabled"
    @change="handleChange"
  >
    <option
      v-for="(option) in options"
      :key="option.value"
      :value="option.value"
      :selected="option.value === value"
      :disabled="option.disabled"
    >
      {{ option.text }}
    </option>
  </select>
</template>

<script>
export default {
  name: "SelectBox",
  props: {
    value: {
      type: String,
      default: ""
    },
    options: {
      type: Array,
      required: true
    },
    disabled: {
      type: Boolean,
      default: false
    }
  },
  methods: {
    handleChange(event) {
      this.$emit("change", event.target.value)
    }
  }
}
</script>
```

プロジェクト直下に.storybook ディレクトリを作成し、その中に下記ファイルを作成
.storybook/config.js

```
import { configure } from '@storybook/vue';


const req = require.context('../stories', true, /\.stories\.js$/);
function loadStories() {
  req.keys().forEach(filename => req(filename));
}

configure(loadStories, module);
```

.storybook/addons

```
import '@storybook/addon-actions/register';
import '@storybook/addon-links/register';
import '@storybook/addon-knobs/register';
import '@storybook/addon-notes/register';
import '@storybook/addon-a11y/register';
import "storybook-addon-vue-info/lib/register";
```

.storybook/webpack.config.js

```
module.exports = ({ config }) => {
  config.module.rules.push(
    {
      test: /\.scss$/,
      use: [
        { loader: 'vue-style-loader' },
        { loader: 'css-loader' },
        { loader: 'sass-loader' },
      ],
    },
    {
      test: /\.vue$/,
      loader: 'storybook-addon-vue-info/loader',
      enforce: 'post'
    }
  )
  return config
};
```

プロジェクト直下にstories ディレクトリ作成し、その中に作成したコンポーネントの.stories.jsファイルを作成

stories/index.stories.js

```
import Vue from "vue"
import ElementUI from "element-ui"
import "element-ui/lib/theme-chalk/index.css"

Vue.use(ElementUI)

// Base Styles for All Components
import "../src/assets/css/base.scss"
```

stories/SelectBox.stories.js

```
import { storiesOf, addDecorator } from "@storybook/vue"
import { withKnobs, boolean, select } from "@storybook/addon-knobs"
import { action } from "@storybook/addon-actions"
import { withA11y } from "@storybook/addon-a11y"
import { withInfo } from "storybook-addon-vue-info"

import SelectBox from "../src/components/SelectBox"

addDecorator(withA11y)

storiesOf("Components", module)
  .addDecorator(withKnobs)
  .addDecorator(withInfo)
  .add("SelectBox", () => ({
    components: { SelectBox },
    data() {
      return {
        value: select("value", {
          apple: "apple",
          orange: "orange",
          mango: "mango",
          banana: "banana"
        }, "orange"),
        options: [
          { text: "りんご", value: "apple" },
          { text: "みかん", value: "orange" },
          { text: "マンゴー", value: "mango", disabled: true },
          { text: "バナナ", value: "banana" }
        ],
        disabled: boolean("disabled", false)
      }
    },
    template: `
      <select-box
        :value="value"
        :options="options"
        :disabled="disabled"
        @change="handleChange"
      />
    `,
    methods: {
      handleChange: action("change")
    },
  }), {
    notes: "",
    info: {}
  })
```

最後にシェルで下記コマンド入力してStorybookを立ち上げる

```
$ npm run storybook
```


以上