Vue、React、Angularで全く同じアプリを作成して比較してみた

#はじめに
元々業務などでVueを取り扱っていましたが、AngularやReactなどの他のフレームワークについても学習中です。
コードレベルでどのように異なるのか？実際に実装を進める上でなにが異なるのか？ということ確かめるために今回実際にVue、Angular、Reactのそれぞれで全く同じアプリを作成して、比較してみました。

今回はそれぞれのフレームワークを利用してみて、感じた違いについてざっくりですがまとめてみようと思います。

## 実際に作成したコード
サンプルとしてはじめに実際に作成したアプリのコードを公開します。
Vue：[コード](https://github.com/shunsato1231/vue-todo/)、[デモ](https://vue-todo-ef767.web.app/)
Angular：[コード](https://github.com/shunsato1231/angular-todo/)、[デモ](https://angular-todo-e5491.web.app/)
React：[コード](https://github.com/shunsato1231/react-todo/)、[デモ](https://react-todo-8b499.web.app/)

簡単なTodoアプリです。
デザインのベースカラーが違いますが、動作は全て同じ物です。

同じ動作のアプリでどのような記述の差があるのか比較しやすいのではないでしょうか。。。



#それぞれのフレームワークの特徴をざっくり紹介
簡単なサンプルコードでそれぞれのフレームワークの特徴を紹介してみようと思います。

## 基本的な構成の違い
基本的な構成を比較するために、まずは変数をそのままHTMLに出力するサンプルコードを比較してみます。

### Vue
HTML、JavaScript、CSSを全てひとつのファイルに書き表します。

```vue:TestComponent.vue
<template>
 <div class="wrapper">{{msg}}</div>
</template>

<script>
export default {
  name: 'app',
  components: {
    TestComponent
  }
 data() {
   msg: 'Hello World!'
 }
}
</script>

<style>
 .wrapper {
  /* ...スタイル記述(略) */
 }
</style>
```

HTML・Javascript・CSSがそれぞれのエリアに分けられて記述されるので、ぱっと見でわかりやすい表示になると思います。
デメリットとしては一つ当たりのファイルの記述が長くなってしまうことでしょうか...

### Angular
ひとつのコンポーネントにたいして、htmlファイル、tsファイル、cssファイルがそれぞれ生成されます。

```html:test.component.html
<div class="wrapper">
  {{msg}}
</div>
```

```javascript:test.component.ts
import { Component } from '@angular/core';

@Component({
 selector: 'app-main-page',
 templateUrl: './app.component.html',
 styleUrls: ['./app.component.css']
 })
export class TestComponent implements {
 msg = 'Hello World!!'
}
```

```css:test.component.css
.wrapper {
 /* ...スタイル記述(略) */
}
```

デザイン部分、マークアップ部分、ロジック部分が完全に分離されたファイルで記述されることになります。マークアップやスタイリングのみを作成する人・ロジック部分を作成する人という感じで作業分担する場合は、作業するファイルを分けられるため効率的だと思います。

しかし、一人で実装する場合はそれぞれのファイルを行き来する必要があるため、可視性が悪く効率が悪かったです。特にHTMLとjavascriptは比較しながら作業を進める必要があるため、頻繁に行き来しなければなりませんでした。


### React
Reactではjsxという記法を用いて記述します。

```jsx:TestComponent.tsx
import styles from './Test.style.css'
const TestComponent () => {
  const msg = 'Hello World!!'
  return (
   <div className="styles.wrapper">
    {msg}
   </div>
  )
}
```

```css:Test.style.css
.wrapper {
 /* ...スタイル記述(略) */
}
```
javascriptの中にHTMLが入り込んだような記述になります。
ここは慣れていない人は少し抵抗を感じるポイントかもしれません。


CSSの記述に関しては様々な方法があり、一般的には

* シンプルなCSSの読み込み
* CSS Modules
* CSS in JS
などの記法が用いられています。

上記のサンプルコードはCSS Modulesを利用した場合の記述になります。

## データバインディングをする場合
Vue、Angular、Reactで下記の仕様のサンプルコードで比較してみます。

* 初期表示は「Hello World!!」
* テキストフィールドに文字を入力するとリアルタイムに表示
* ボタンを押すと「updated!!」と表示


### Vue
```vue:TestComponent.vue
<template>
 <div class="wrapper">
  <span>{{msg}}</span>
  <input type="text" v-model="msg"></input>
  <button @click="updateMsg()"></button>
 </div>
</template>

<script>
export default {
  name: 'app',
  components: {
    TestComponent
  }
 data() {
   msg: 'Hello World!'
 }
 methods: {
  updateMsg() {
   this.msg = 'updated!!'
  }
 }
}
</script>

<style>
 .wrapper {
  /* ...スタイル記述(略) */
 }
</style>
```
Vueの場合、```v-model```というハンドルを使用すると、双方向バインディングを実装することができ、テキストボックスの変更をJacascriptの変数に反映させることができます。
また```@click```(v-on記法)を利用することで、ボタン押下時も値を変化させています。

### Angular

```html:test.component.html
<div>
 <span>{{msg}}</span>
 <input type="text" [(ngModel)]="test" />
 <button (click)="updateMsg()">update!</button>
</div>
```

```ts:test.component.ts
import { Component } from '@angular/core';
@Component({
 selector: 'app-main-page',
 templateUrl: './app.component.html',
 styleUrls: ['./app.component.scss']
 })
 export class AppComponent implements {
  test: string;
  updateMsg(): void {
    this.msg = 'updated!';
  }
}
```
Vueと同様に```[(ngModel)]```記法を利用することで、双方向バインディングを実装することができます。ボタンの変更は```(click)```と記述することでjavascript側の関数を実行させています。

### React
```jsx:TestComponents.tsx
const TestComponent = () => {
  const [msg, setMsg] = useState('Hello World!!')
  const updateMsg = () => {
    setMsg('updated!!')
  }
  const handleChange(event) = () => {
    setMsg(event.target.value)
  }

  return (
   <div>
    <span>{msg}</span>
    <input type="text" onChange={handleChange} />
    <button onClick={updateMsg}>update!</button>
   </div>
  )
}
```
Reactではデータの値を保持するために```useState```と呼ばれるフックを利用します。値を更新する際は明示的にjs側から```setMsg```を実行しない限り値は更新されません。

Reactは双方向のバインディングがなく、データフローが単方向に絞られています。
そのため、```handleChange```をテキストが更新された時に実行させ、js側のデータを変更しています。

jsの関数をセットする際は```onClick```や```onChange```など、ネイティブのjavascriptと同じような記述方法になります。



#それぞれのフレームワークで開発してみた感想
それぞれの言語でTODOアプリを開発して、個人的に感じた感想を挙げてみようと思います。

##Vue
Vueは基本的に扱いやすく、初学者でも難しいロジックなどの実装をしなくてもある程度の物が作成できるような気がしています。

### 良いと思ったところ
#### ◎ CSSの取り扱い
基本的にVueテンプレートのスタイルブロックの中で記述すれば良く、管理に迷うことがありません。
視覚的にブロックも分かれているので可視性も良いと思います。
```<style scoped>``` である程度汚染を防げますし、それでも防げない外部CSSの影響も避けたい場合は記述が多少頻雑になりますが、```<style modules>```で記述するという手段もあります。


#### ◎ 日本語ドキュメントの豊富さ
基本的にどこを見ても日本語のドキュメントが揃っているため、情報収集が他の2つと比べてしやすいと感じました。

#### ◎エコシステムの豊富さ
「vuex」や「vue-router」などのエコシステムが公式orgの元で開発されており、どれを使ったら良いのかを迷う必要がありません。ばらつきもないので情報も集めやすいところは利点だとおもいました。

### いまいちだと感じたところ
#### △Component.extendのオプションがとにかく多いところ
```data``` 、 ```props``` 、 ```methods``` 、 ```computed``` 、```watch``` ...etc オプションが多く、覚えることが多い気がします。

#### △v-ifやv-forなどのテンプレートに直接記述するディレクティブ
```v-if``` や ```v-for``` などのをHTMLに組み込むような形で書かなくてはいけないのはなんとなく可視性が悪いと個人的に感じています。
とくに```v-for``` なんかはJavascriptの構文とも少し違ったような形になっていて、少し書きにくいと感じてしまいます。

## Angular
他ふたつのフレームワークと比べて、深堀できていないのであまり多くを語れませんが、この３つのフレームワークの中ではダントツに難易度が高いと感じました。
独自の仕様が多く、モジュール、依存性注入、修飾子、コンポーネント、サービス、パイプ、テンプレート、命令文...etc 概念から学ばなくては理解できないようなことがたくさんあり、新しい言語をひとつマスターするくらい大変なのではないか？という印象です。

###いいと感じたところ
####◎とにかく全部揃っているところ
状態管理やルーティング、サーバからのデータの取得まで、自分で他のエコシステムなどを用意してこなくても、最初から全て導入されている状態です。
### いまいちだと感じたところ
####△HTML、CSS、Javascriptのコードが全て別ファイルなこと
前述しましたが、可視性が悪くファイル同士の行き来が大変でした。
####△とにかく難易度が高いところ
チュートリアルをやってみただけでも、理解が難しいような新しい概念がたくさん登場します。

見様見真似でなんとかTodoアプリを作成しましたが、Angularに関してはまだ全然理解が追いついていません...😨

##React
Reactは他二つと比べるとかなり単純なフレームワークなのではないかと思います。
しかし、そのためJavascriptで自前で用意しなければいけない箇所も多い印象です。

そのためJavascriptに慣れている人にとっては学習コストが低いのかな？と思いますが、そうでない方にとってはVueよりも少しとっつきにくいかもしれません。

### 良いと感じたところ
#### ◎Javascriptの構文を、domの生成にそのまま使えるところ
DOMの繰り返し表示(forやmap)や、分岐(if)などはHTMLの中にJavascriptのコードをそのまま埋め込むような形で記述することになります。
Javascriptに慣れている人にとってはわかりやすく、迷いが少ないと思います。

#### ◎覚えることが少なく、Javascirptの構文のままかけること
Reactの場合は基本的に ```state```、```props```、```render```が分かっていれば基本的には完結してしまうような単純さがあります。
しかし逆を言うと、シンプルな分、自力で実装しなければいけない箇所が多い印象です。

#### ◎単一方向バインディング
Reactでは基本的にJavascriptで変更したコードが見た目に適応されます。双方向にデータが変更されることがないため、複雑化しにくく扱いやすいと感じています。

### いまいちだと感じたところ
#### △CSSの取り扱い
styled-componentsやCSSModuleなど様々な管理方法がありますが、これと言った決定打がなく、実装者によってかなりばらつきがあると感じました。
どれを採用していいのか迷いますし、ばらつきがあるためそれぞれの情報量も少なく、どう実装を進めて行けばいいのか最初かなり迷いました。

#### △エコシステムにもばらつきがあるところ
代表的なもので、状態管理をするための```redux```やルーティング管理の```react-router```などがありますが、Vueと比べると利用状況にばらつきがあるように思いました。
そのためどれを利用していいかを選定する必要があり、ハードルが高いように思います。


# 最後に
最終的にどれを選ぶかは好みの問題も大きいと思います。
私は一通り軽く触れて見たところReactがお気に入りで、Reactを採用して個人開発などをしています。