jQueryメインのエンジニアがVue + Vuex, React +Reduxを触ってみて使用感をまとめる

# はじめに
普段の業務ではサーバサイドとフロントのJavaScript部分の実装を行っております。
VueやReactのような新しいライブラリを利用したJavaScriptの実装感について知りたいと思い、同じ機能を両者で実装してみて使用感をまとめてみました。
(結論から言うと個人的に採用するならばVue + Vuexの方が実装しやすいと感じました)

※属性の参考になるかもしれないので、普段の業務でのJavaScriptの開発スタイルを注釈に記載します。[^1]
[^1]: 普段のフロントの業務では、(1)jQueryでイベントハンドラやDOM操作をコンポーネントごとに実装, (2)コンポーネント間の連携にPub/Subパターンを提供するライブラリ、(3)テンプレートエンジンを利用してテンプレートを作成 のような形でやっています。

# 作ったもの
以下のようなシンプルなアプリケーションを作りました。
![スクリーンショット 2019-04-07 13.21.43.png](https://qiita-image-store.s3.amazonaws.com/0/280433/52a5912b-289c-d409-cbaf-de2cbf85dfe7.png)

実装した機能は3つです
1. 部屋データを動的にレンダリングできる(データ自体は固定のモック)
2. プルダウンメニューより、「賃料」が高い/低い順でソートできる
3. 「部屋をもっと見る」をクリックすると隠れた部屋を表示することができる

実際のコードは下記を参照ください。

**JSFiddle**
[Vue + Vuex](https://jsfiddle.net/moehiko/gqxLkcmw/)
[React + Redux](https://jsfiddle.net/moehiko/2rc6vpas/)

# 比較早見表
実装していて気になった点の比較下記にまとめます。
(初めてQiitaのテーブル使いましたがなかなかしんどいですね)

## Vue vs React
|観点|Vue |React|  
|---|---|---|
|リファレンス  |公式に日本語ドキュメントあり  |公式に日本語ドキュメントはない|
|コンポーネントの仕組み|あり|あり|
|データバインディングの仕組み|あり|あり|
|イベント通知/購読の仕組み|あり(emit/on)|なし(別途ライブラリが必要)|
|条件分岐/繰り返し|viewに用意されたディレクティブを利用|別途JavaScript記法での実装が必要|

コンポーネントやデータバインディングの仕組みはほぼ同じでしたが、
Vueにはif, for文のようなディレクティブが豊富に用意されており、テンプレートエンジンに慣れていた私には馴染みやすいものでした。

一方でReactはView側にJavaScript記法での実装が必要で、慣れないせいか不便に感じてしまいました。
プログラミングに慣れている人なら大きな問題ではないと思いますが、マークアップエンジニアからフロントエンドエンジニアへのスキルアップを考えている方の場合はVueの方が理解しやすいように感じます。

以下にコードの例を記載します。

### 条件分岐
#### Vue
```
templte:
 <div v-show="index < 3">
  hoge
</div>
```
#### React
```
{ index < 3  ? <div>hoge</div> : ''}
```
### 繰り返し
#### Vue
```
<div class="parents">
  <div v-for="(room, index) in rooms">hoge</div>
</div>
```
#### React
renderメソッド内で配列の作成が必要

```
// renderメソッド内
let list = []
for (var i in rooms) {
  list.push(<div>hoge</div>);
}
// return内
<div className="parent">
  {list}
</div>
```

## Vuex vs Redux
先に彼らが何者かを調べました。
### Vuex Reduxとは
* 状態管理パターンを提供するライブラリ
* 共にFluxの思想に乗っ取っている　
※ここでのFluxは設計思想での意味

状態遷移パターンを用いることで、状態の変化を一定方向に制限し長期的なメンテナンス性を向上させられる　というメリットがあるようですね。

# 比較早見表

|観点|Vue |React| 
|---|---|---|
|状態管理の仕方|view→action→mutation→store|view→action→reducer→store|
|実装感|store内にmutation, actionを実装|store, reducer, actionは別箇所に実装|

共にFluxパターンに乗っ取っているため、状態管理の仕方はほぼ同様でした。
Dispatcherの名称がVuexはmutation、Reactはreducerと呼ぶことくらいでしょうか。
実装感としてはVueの方はStore内にmutation/actionを定義するため、状態に関わる処理がまとまっているように感じ、わかりやすい印象を受けました。
対してReactは各状態に関する処理はそれぞれ並列のスコープに実装し、どの状態に関する処理が追いにくい印象がありました。
(ただここは私のReact経験が浅いからかもしれません...)
下記に実装のイメージを記載します、尚コードは説明用のために先のリンクのサンプルコードの実装内容を省略したものを利用しています。

## Vue
```
const store = new Vuex.Store({
  // store
  state: 0,
  // mutation
  mutations: {
    sort (state) {
      // do something
    },
  // action
  actions: {
    sort (context) {
      context.commit('sort')
    }
  }
})

// view
const contents = new Vue({
  el: '#contents',
  store,
  template: `<div>hoge</div>`
})
```

## React
```
const {createStore} = Redux;

// Action名の定義
const SORT = 'SORT';
      
// Action Creator
function sort(value) {
  // Action
  return {
    type: SORT,
    value,
  };
}

// Reducer
function reducer(state, action) {
  switch (action.type) {
    case SORT:
      // do something
    default:
      return state
  }
}

// store
// 初期state変数（initialState）の作成
const initialState = {}

// createStore（）メソッドを使ってStoreの作成
const store = createStore(reducer, initialState);

// View
class Contents extends React.Component {
  render() {
    return (
      <div>hoge</div>
    )
  }
}        
```

# おわりに
色々と比較しましたが、特にVueの方がやりやすそうだなと思った観点を記載します。

1. 普段テンプレートエンジンを利用しているので、ディレクティブが豊富だと嬉しい
2. フロントエンドスキルを高めたいマークアップエンジニアがとっつきやすそう
3. 次点：Pub/Subパターンを提供する仕組みを自前で持っている

2は一緒に開発を行うエンジニアのスキルセットやキャリア志向によって変わりそうです。
また3は、Reactでも別ライブラリを導入すればこの点はあまり有位にならないかもしれません
また、今回はStoreによるデータバインディングの仕組みで事足りたため、
Pub/Subパターンの導入が本当に必要かどうかはもう少し深掘りが必要かなと思っています。

# 参考
[Vuex とは何か？](https://vuex.vuejs.org/ja/)
[Flux を使わずに React コンポーネント間のコミュニケーションを行う8つの方法](https://qiita.com/kyoshidajp/items/0ddb156d96bb6337f623)
[[フロントエンド] React.jsのJSXで条件分岐を表現する方法（5つ）](https://www.yoheim.net/blog.php?q=20180409)
[Reactの単純なサンプルでFluxの実装を解説](https://mae.chab.in/archives/2747#post2747-1)