初めてVue.jsに触れた頃の私へ今の私が伝えたいTips コンポーネント分割/ライブラリ選択編

# Vue.js初学者の頃の私にメッセージが届けられるなら
私が一人で Vue.js に挑戦していた頃、これでいいのかなぁ？一番いい方法ってなんだろう？みたいなことをたくさん悩みました。
そんな私へ、今の私ならこう答えるよ、というものをまとめてみました。

- 注意書き
 - 初めてVueに触れた頃の私
  - jQueryでそれなりぽいものをそこそこ作ってた
 - 今の私(2018年7月)
  - 個人開発でVueを使ってそれなりにぽいものを2、3個作った
  - 勉強会やイベントに参加して見聞きしたり発表したり
  - Vue.jsはいいぞってイキっている

この記事がVue.jsの他の初学者の方にも参考になれば幸いです。


## コンポーネントの分割について
コンポーネントの分割は、初めは本当に考えなくていいんじゃないかと思っています。

SPAなら画面1枚分、部分的に作るならそのパーツ1つ分を作りきってしまうと、
目的のモノを作るのに素早いスタートを切ることができます。

データの受け渡しについて考えるのって変にハマりやすいと思っているんですよね。

作り込んでいく上で、コンポーネントの分割が必要だなと感じたら、
主に次の2つ文脈でコンポーネントを切り出すのがいいかなと思います
- 2個目の画面を作るので、共通の要素を切り出したい
- コンポーネントの見通しが悪いから切り出したい

これらの場合、その文脈に沿って切っていくのがいいと思います。

### コンポーネント化の粒度と設計に悩んだときのヒント
命名や分類で悩んだら、 Atomic デザインという設計原則が非常に参考になりました。
ちょっと見慣れない単語なので戸惑いましたが、分割の原則がVueのコンポーネント化と非常にマッチしていると思います。

- [珍しいワークフロー：Atomic Designの原則とSketchでデザインからプログラミングまで \| POSTD](https://postd.cc/the-unicorn-workflow-design-to-code-with-atomic-design-principles-and-sketch/)

うーん、VueでAtomicデザインに沿ってコンポーネントを作る時、データを受け取らないAtomsと受け取って動作するAtomsを分けて考えるといいよみたいな記事を読んで感銘を受けた覚えがあるのですが見つけられません……
ご存知の方がいればご一報いただけると嬉しいです。

### 密結合なコンポーネント間のめんどくさくないデータのやりとり
多くの記事でコンポーネント間のデータのやりとりは「props down、 event up」で作りましょうとか、「Vuexを使うといいよ！」みたいな記事がすっごいたくさんでてきます。

ところで、今切り出したコンポーネント、使い回す予定がありますか？
さらに、子コンポーネントで状態が変わったら親コンポーネントでも値を同期していてほしいっていうことはありませんか？

後々の設計的にあまり褒められたことではないかもしれませんが、
「あえてpropsにObjectを渡して、渡されたObjectをそのまま操作する」という方法があります。

こうすると、データの受け渡し周りについて全く考えなくていいので楽できます。


言うまでもありませんが、密結合なコンポーネントがたくさん出来てしまった結果、
予想外のデータ変更が起こってしまったというバグは考えられます。

あくまで密結合なデータのやり取りはスコープを限定するなど、
乱用しない自制心が必要です。





## ライブラリなど
### vue-router
コンポーネントの移動でブラウザのアドレスバーのURLを書き換えていったり、
URLから最初にレンダリングするコンポーネントやデータを書き換えるための公式ライブラリです。

ページ遷移的な表現がプロジェクトに増えてきたタイミングで導入すると捗ると思います。

### vuex
fluxアーキテクチャをvueで使うための公式ライブラリです。
コンポーネントが増えてきて、「どのコンポーネントからでも参照したい」「どのコンポーネントからでも書き換えたい」みたいなシチュエーションが発生したら導入すべきでしょう。

データをバケツリレーせず、vuexから直接データを取り出せます。
逆に、コンポーネントをまたがってデータを扱いたいみたいなシチュエーションでは、コードが複雑になるのでまだ必要じゃないでしょう。

また、「vuexを導入したからデータは全部vuexに載せる」というのはアンチパターンらしく、管理が煩雑になるので必要な部分だけvuexにデータを格納するという使い方がいいみたいです。

### UI コンポーネントライブラリ
疎結合なコンポーネントを作れば、プロジェクトの他の部分へ影響の与えないカスタムタグのような形で気軽に呼び出して使えます。
ということで、そのようなコンポーネント集をライブラリとして公開してくれているものがあるので、いくつか紹介します。

#### Element
いつの間にか Element React とか Element Angular とかできてましたけど、
発端はVue用のライブラリです。

簡単に使える綺麗なコンポーネントが揃っていているだけでなく、
プロパティで挙動をカスタマイズできるようになっていたりして非常に使いやすいです。

- [Element \- A Desktop UI Toolkit for Web](https://element.eleme.io/#/en-US)

#### Bootstrap Vue
Vue.jsは仮想DOMから実際のDOMを書き出し続けるという性質上、
他の方法で直接DOMを書き換えてしまうと何が起こるかわかりません。

ということで、生DOMを書き換えまくるjQueryとは相性が悪く、
jQueryを使うBootstrapとも当然相性が悪いです。

しかし、Bootstrap VueはVue.jsでBootstrapの各コンポーネントを作り直しているので、
「Vue.jsでもBootstrapを使いたい」ときには良いチョイスなんじゃないかなと見ています。

Bootstrap V4 ベースで作られています。

- [Bootstrap Vue](https://bootstrap-vue.js.org/)

### データ操作用のnpm packageのよさげなやつ
Rodash - 関数型配列操作など
moment.js - 時間関係のパーサ、コンバータ
string.js - Stringクラスの強いやつ
URI.js - URIやクエリストリングを扱う
store.js - LocalStorageのwrapper
axios - ajaxコール用ライブラリ（Vueと一緒に入ってくると思う）

## まとめ
コンポーネント分割/ライブラリ選定編のTipsは以上となります。
「何が一番よい方法なのかわからない！」「本当にこの方法であってる？」って悩んでいた私に伝えたいことコンポーネント分割/ライブラリ選定編でした。

コンポーネント分割については作っているものが小さな間は本当に必要に駆られた時初めて考えればいいと思っています。
一人プロジェクトなら大きくなっていくに従って、Atomicデザインに従った分割の仕方に変えていくとスムーズなんじゃないかなと。

逆に、複数人で開発していくならAtomicデザインによるそれぞれの領分を分けることで、
規模が大きくなっても開発スピードを落とさないでいられるんじゃないかなあと思っています。
（が、今の所複数人でVueを書いた経験はありません……）


ライブラリについては、本当に主要なものを一通りといった感じなので、
 [vuejs/awesome\-vue: 🎉 A curated list of awesome things related to Vue\.js](https://github.com/vuejs/awesome-vue) を眺めながら良さげなものを導入していくと良さそうです。

npmの便利ライブラリなんかは、知ってればそっち使ったのに！みたいなのもあるのですが、
VueではなくそもそもJSの話になってしまうので、こんなのもあるんだよ！っていう形で紹介しました。

こちらも暇なときに[sorrycc/awesome\-javascript: 🐢 A collection of awesome browser\-side JavaScript libraries, resources and shiny things\.](https://github.com/sorrycc/awesome-javascript)を眺めると楽しいかもしれません。

Vue.js開発は本当に楽しいです！Vue.jsはいいぞ！

### こんな記事も書いてます
- [初めてVue\.jsに触れた頃の私へ今の私が伝えたいTips プロジェクト作成編 \- Qiita](https://qiita.com/fruitriin/items/dcb8fdad117591c0f402)
- [私がハマったVue\.jsのショボいミス \- Qiita](https://qiita.com/fruitriin/items/fe26e3ecb33000a6544e)
- [LaravelからVue\.jsを使う最短レシピ \- Qiita](https://qiita.com/fruitriin/items/e0f2c9aa035c3ff2c874)