LoginSignup
17
14

More than 3 years have passed since last update.

Vueのディレクトリの責務について考える

Last updated at Posted at 2019-10-19

vue-cliで生成した状態でsrc以下はこうなっています。(assetsは省略)

├── components // コンポーネント
├── views // ページと1:1
├── App.vue // トップページのコンポーネント
├── main.js // プラグインの使用など
├── router.js // ルーティング
└── store.js // Vuex

もちろんこのままゴリゴリ書いていくことも可能ですが、components以下にロジックが大量にかかれ、共通化されてない見通しの悪いコードが生成されることになります。

コンテナコンポーネントを追加する

コンテナコンポーネントを入れるcontainersを追加しました。

├── components // コンポーネント
├── containers // コンテナコンポーネント
├── views // ページと1:1
├── App.vue // トップページのコンポーネント
├── main.js // プラグインの使用など
├── router.js // ルーティング
└── store.js // Vuex

コンテナコンポーネントとは何でしょうか?

  • Vuexを知っている
  • 他のコンテナコンポーネントを呼び出してもよい
  • ラッパーのdivを除いて独自のDOMマークアップは書かない

以下の記事がすごくわかりやすいのでぜひ一度読んでみてください。

2018年Vue.jsとVuexを使ってる人に提案するコンポーネントの分類と設計パターン - Qiita

コンテナコンポーネントにロジックを寄せることでcomponents以下ではpropsで値を受け取るだけでよくなり、テストも書きやすくなります。
ですが、ロジックがcontainers以下に移動しただけなので、次はcontainersの見通しが悪くなりました。
ロジックの置き場所を考える必要がありますね。

componentsを整理する

ロジックの置き場所を考える前に、components以下をpropsで受け取ったコンポーネントの書き方のポイントを紹介します。

  • v-model
  • emit or callback

v-modelは糖衣構文

v-modelと書くだけでテキストをリアクティブなデータを扱えるのはすごく便利なのですが、v-bindv-onv-modelとか最初の方は混乱しますよね。v-modelは糖衣構文なのでv-bindv-onを使って書き換えることができます。(:はv-bind、@はv-onの省略記法)

<input v-model="text">

<input :value="text" @input="text=$event.target.value">

emit or callback

どちらも子から親に変更を伝えることができます。(親からpropsで受け取った値は基本的に子側で変更できないので、変更を伝える必要があります。)
最初はemitを使ってたのですが、Vue固有の書き方なので少しコードを書かないと使い方を忘れることがよくありました。callbackならVueが初めての人も分かる書き方なので個人的にはコールバック方式をオススメします。

v-modelemit or callbackを理解しておくことで、コンポーネントには一切の状態(data)を持つことなく、propsから値を受け取るだけのシンプルなコンポーネントになります。(ステートレスコンポーネント)

以下のItemList.vueは親から受け取ったfilter.userIdをv-modelで指定していますが、オブジェクトのプロパティなので子側でも書き換えができます。

components/ItemList.vue

API通信を分離する

現在はcontainersでaxiosをimportしているので、テスト時にaxiosをモック化する必要があります。また、axios以外のライブラリを使うことになった場合など変更が容易ではありません。
以下の記事を参考にrepositoriesを作成します。

【Vue.js】Web API通信のデザインパターン (個人的ベストプラクティス) - Qiita

今回はQiitaのAPIをコールするだけなので少し簡略化しています。また、axiosを知っているのはrepositories以下のみにしたいのでAxiosPromiseを返さずPromiseを返しています。

src/repositories/qiitaRepository.ts

containers/Directory.vue

コンポーネントからAPIを呼ぶコードのテストではAxiosMockなどを使わずにqiitaRepositoriesをsinonなどでstub化すればいいかと思います。

ここまでのディレクトリ構成

├── components // ステートフルコンポーネント、ステートレスコンポーネント
├── containers // コンテナコンポーネント
├── repositories // API通信
├── views // ページと1:1
├── App.vue // トップページのコンポーネント
├── main.js // プラグインの使用など
├── router.js // ルーティング
└── store.js // Vuex

今回はこれで終わりです。

次回はservicesとmodelsを追加したパターンを紹介したいです。

Vueのディレクトリの責務について考える(2) - Qiita

17
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
14