Vueseを使ってみた 〜Vue.jsでコンポーネント一覧（スタイルガイド）を作成〜

プロジェクトでコンポーネント一覧作成のため、vueseを検証したので使い方の備忘録。

# 対象読者
vueの基本的な知識をご存知の方であれば問題ありません。
具体的には、下記を満たす方であれば余裕で理解できる内容かと思います。

・vueを使用しているプロジェクトでコンポーネントを作成、修正した経験がある。あるいは入門書籍を読破した、個人で動かしたことがあるなど。
・props、events、slot、methodsを定義したことがある。

# 導入
```
npm i -D @vuese/cli
# yarn add -D @vuese/cli
```

# 使い方
使い方を解説します。
前提として、プロジェクト構成は以下とします。

```
root
├── src
├──├── components
├──├──├── atoms
├──├──├──├── TestButton.vue
├──├──├──├── TestInput.vue
├──├──├── molecules
├──├──├──├── TestSearch.vue
├──├──├── organisms
├──├──├──├── TestHeader.vue
├──├──├── pages
├──├──├──├── TestPage.vue
├──├──├── templates
├──├──├──├── TestDefaultTemplate.vue
```

## 注意点
以下のいずれかの条件を満たすコンポーネントのみ、ドキュメント生成対象となるようです。(参照: [@vuese/cliのPrecautions](https://vuese.github.io/website/cli/#precautions))

条件
・Propsが定義されている
・Eventsが定義されている
・Slotsが定義されている
・Methodsに`@vuese`アノテーションのコメントの記載のあるメソッドが定義されている
・コンポーネントに`@vuese`アノテーションのコメントの記載がある

以下、ドキュメント生成対象となる定義、記載例。
```
例: props

props: {
    test: String
}
```
```
例: events

this.$emit('test', true);
```
```
例: slots

<slot></slot>
```
Props、Events、Slotsは定義するだけで対象となるようですが、
Methodsについては下記のように、各メソッドに`@vuese`アノテーションのコメントを記載をしないといけないようです。
```
例: methods

methods: {
　　　　// @vuese
　　　　test() {
  　　　　alert('test');
　　　　}
』
```
props、events、slots、methodsの定義がない場合でも、下記のように、`export default`の前の行に`@vuese`アノテーションのコメントを記載すればドキュメント生成対象となるようです。
```
// @vuese
export default {
    name: 'TestComponent',
}
```

## コンポーネント一覧を作成する
各vueファイルの`export default`直前に、`@vuese`アノテーションのコメントを記載し、プロジェクトのルートで以下のコマンドを実行します。
```
vuese gen
# npx vuese gen
```
プロジェクトのルートにwebsiteというフォルダが作成されます
```
root
├── website
├──├── index.html
├──├── components
├──├──├── TestButton.md
├──├──├── TestDefaultTemplate.vue
├──├──├── TestHeader.vue
├──├──├── TestInput.vue
├──├──├── TestPage.vue
├──├──├── TestSearch.vue
```
続いて以下のコマンドを実行
```
vuese serve --open
```
サーバーが起動してブラウザが開き、コンポーネント一覧が表示されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676513/68e73c91-f40f-d785-d22b-0c98bde2122b.png)
以降TestHeaderを例として使用するので、TestHeaderのドキュメントを表示しています

## package.jsonにスクリプトを追加
コンポーネントを追加、修正した後、コンポーネント一覧を開く度に、websiteフォルダを削除して、`vuese gen`、`vuese serve --open`のコマンドを打つのは手間なので、package.jsonにスクリプトを追加しておきます。
package.jsonのsciriptsに下記を追記します。
```
"scripts": {
    "doc:gen": "rm -rf website && vuese gen",
    "doc:serve": "vuese serve --open",
    "doc": "npm run doc:gen && npm run doc:serve"
},
```
以降、コンポーネント一覧を開く際は、`npm run doc`コマンドをプロジェクトルートで実行します。

## コンポーネントの説明を記載する
複数人で開発している場合、作成済みのコンポーネントがどのような役割か、どこでどのように使われるか、説明が記載されていると開発済みの(使い回し出来る)コンポーネントの把握、共有がしやすいと思います。
`export default`の直前にコメントを記載すれば、コンポーネントの説明を記載出来ます。
TestHeader.vueを例にして書き方を紹介します。
TestHeader.vueの`export default`の行の直前に以下のコメントを記載します。
```
/*
 * @vuese
 * 全画面共通のヘッダコンポーネント
 */
```
再度、コンポーネント一覧を開き直します。(`npm run doc`コマンドをプロジェクトルートで実行)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676513/5e365179-4ed4-fbf5-be46-25948d04c4f9.png)
TestHeaderコンポーネントに説明が記載されました。

## Props、Events、Slots、Methodsの項目を表示する
引き続き、例としてTestHeaderコンポーネントを修正します。
TestHeader.vueのコードを下記のように修正します。
```
<template>
  <header>
    <h1>{{ testTitle }}</h1>
    <slot>
    </slot>
    <TestSearch/>
  </header>
</template>

<script>
import TestSearch from '@/components/molecules/TestSearch'

/*
 * @vuese
 * 全画面共通のヘッダコンポーネント
 */
export default {
  name: 'TestHeader',
  components: {
      TestSearch
  },
  props: {
    testTitle: {
        type: String,
        required: true,
        default: 'test'
    }
  },
  methods: {
    /* 
     * @vuese
     */
    testMethod(test) {
        alert(test);
    },
    testEvent() {
        this.$emit('test', true);
    },
  }
}
</script>

<style scoped>
</style>
```
再度、コンポーネント一覧を開き直して確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676513/19952451-e198-952a-9d8e-f1d26412db8a.png)
Props、Events、Slots、Methodsの項目が表示されました。

## Props、Events、Slots、Methods、それぞれの詳細の書き方
引き続き、例としてTestHeaderコンポーネントを使用します。

### Props
testTitleを下記のように修正します。
```
// ヘッダのタイトル
testTitle: {
    type: String,
    required: true
    default: 'test'
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676513/7d169713-46a4-224b-cc76-120275b73792.png)

### Events
testEventを下記のように修正します。
```
testEvent() {
    /*
     * テスト用のイベント
     * @arg 引数はbooleanです
     */ 
    this.$emit('test', true);
},
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676513/72c4f6ea-e39c-cbf0-b3df-ca81ead8ec0d.png)

### Slots
slotタグの部分を下記のように修正します。
```
<!-- ヘッダーのスロットのコンテンツ -->
<slot>
    <!-- `<p>デフォルト</p>` -->
    <p>デフォルト</p>
</slot>
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676513/e1c92716-461d-b507-fa8b-a9a3570dae5f.png)

### Methods
testMethodを下記のように修正します。
```
/* 
  * @vuese
  * テスト用の関数
  * @arg 引数はtestです
  */
testMethod(test) {
    alert(test);
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676513/f5b3b879-864f-02f1-7c09-08d8c4c203e3.png)

## コンポーネントをグループ化する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676513/46312e4f-a2ab-495e-3ca4-036b6cc9d34f.png)
全てのコンポーネントがサイドメニューに一列で表示されていますが、コンポーネントの種類によってグループ化してまとめたいと思うかもしれません。
各コンポーネントの`export default`直前に`@group (グループ名)`とコメントを追記すると記載したグループ名ごとにコンポーネントをグループ化することが出来ます。
この記事では、プロジェクトをアトミックデザインの考え方を参考に作成しており、コンポーネントの種類によってディレクトリ単位で分類しています。
そのため、これから紹介する例でも、ディレクトリの構造と一致する形でグループ化したいと思います。
各コンポーネントのVueファイルの`export default`の行の直前のコメントを以下のように修正します。

---
- TestButton.vue
```
/*
 * @vuese
 * @group atoms
 */
```
---
- TestInput.vue
```
/*
 * @vuese
 * @group atoms
 */
```
---
- TestSearch.vue
```
/*
 * @vuese
 * @group molecules
 */
```
---
- TestHeader.vue
```
/*
 * @vuese
 * 全画面共通のヘッダコンポーネント
 * @group organisms
 */
```
---
- TestPage.vue
```
/*
 * @vuese
 * @group pages
 */
```
---
- TestDefaultTemplate.vue
```
/*
 * @vuese
 * @group templates
 */
```
---
再度、コンポーネント一覧を開き直します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676513/42f292ed-9279-852c-5868-3d48178ee40b.png)
コンポーネントがグループ化されました。

## 感想
ドキュメント生成対象となる定義がない場合、生成対象とするためにコメントを書かないといけないこと。一覧グループ化の為に各ファイルにコメントを書かないといけないことが少し面倒かなという印象でした。
特に後者は、設定すればディレクトリ単位でグループ化出来ると嬉しいかなと思いました(もしこれが可能で、方法ご存知のいらっしゃれば是非ご教示頂けますと幸いです)。

## 参考
https://vuese.github.io/website/cli/