導入
現代のフロントエンドといえば React.js と Vue.js の 2 強ですよね。
私は React には触れたことはあるので基本はある程度わかっているのですが、Vue は全く触れたことはありませんでした。
そこで今回は Vue3 の現時点(2022 年 5 月)で最新の書き方を、React と比較しながら学んでみます。
ちなみに私はフロントエンドを学んで日が浅いので、書き方がおかしいところがあるかもしれませんが、大目に見ていただけると嬉しいです m(_ _)m
(お問い合わせフォームでこっそり指摘していただけると非常に助かります)
構文変化の歴史
React も Vue も書き方は時が経つにつれて変化しています。
ここではそれぞれの違いを簡単に見ていきます。
React
React は大きく分けてクラスコンポーネントと関数コンポーネントに分かれます。
クラスコンポーネント
関数コンポーネントで state が管理できるようになるまでは、こちらの書き方が主流でした。
Java のようにクラスを作るのが特徴です。
class Counter extends React.Component { constructor(props) { super(props) this.state = { count: 0, } }
increase() { this.setState({ count: this.state.count + 1, }) }
render() { return ( <div> <p>合計:{this.state.count}</p> <button onClick={() => this.increase()}>クリック</button> </div> ) }}
関数コンポーネント
クラスの代わりに関数を使ってコンポーネントを定義します。
関数コンポーネントで state を管理できる React Hooks が登場してからはこちらが主 流の書き方です。
より簡潔に書けます。
const Counter = () => { const [count, setCount] = React.useState(0)
const increase = () => { setCount(count + 1) }
return ( <div> <p>合計:{count}</p> <button onClick={increase}>クリック</button> </div> )}
Vue
Vue は Vue2(Options API)と Vue3(Composition API)に分かれ、Vue3 の中でも Vue3.2 以降は<script setup>
構文が使えるようになりました。
Vue2 (Options API)
Vue2 ではコンポーネントを data()と methods に分けて書きます。
React のクラスコンポーネントに近い印象です。
<template> <div> <p>合計:{{count}}</p> <button @click="increase"> クリック </button> </div></template>
<script>import Vue from "vue";export default Vue.extend({ data() { return { count: 0; }; }, methods: { increase() { this.count++; } },});</script>
Vue3 (Composition API)
Vue3 では setup()内に data()と methods を ES6 以降の JavaScript のように書けるようになりました。
template 部分は Vue2 と変わりません。
<template> <div> <p>合計:{{count}}</p> <button @click="increase"> クリック </button> </div></template>
<script>import {defineComponent, ref} from "vue";
export default defineComponent({ setup() { const count = ref(0);
const increase = () => { count.value++; };
return { count, increase, }; },});</script>
Vue3.2 (<script setup>
構文)
Vue3.2 以降では setup()内の記述を<script setup>
を使うことで直接書けるようになりました。
React の関数コンポーネントの書き方とかなり近い印象があります。
<script setup>import {ref} from "vue";
const count = ref(0);
const increase = () => { count.value++;};</script>
<template> <div> <p>合計:{{count}}</p> <button @click="increase"> クリック </button> </div></template>
スポンサードリンク
Vue3 と React の最新の書き方の比較
ここからは、Vue3.2 以降の<script setup>
を使った書き方を、関数コンポーネントを使った React と比較することで学んでいきます。
このために、以下の簡単な Web アプリを作って比較することにしました。
これは増加量に 0 以上の数字を入れ、「足す」ボタンを押すとその増加量分合計に足されるものです。
「リセット」ボタンを押すと合計が 0 に戻ります。
また、入力に問題がある場合、アラートが出ます。
実際に完成したものはこちらにあるので、確認してみてください。
React 版はこちら
Vue3 版はこちら
それでは、React と比較しながら学んでみたいと思います。
以下のステップで学んでいきます。
- プロジェクトの作成
- プロジェクトの起動
- 全体の構成
- App コンポーネントの比較
- Adder コンポーネントの比較
- GitHub Pages へのデプロイ
プロジェクトの作成
まず、プロジェクトの作成方法の比較です。
Vue では、React のcreate-react-appの代わりにcreate-vueを使用します。
React
npx create-react-app sample-app
Vue3
(後の質問はすべて No で良い)
npm init vue@3 sample-app
TypeScript を使用する場合は以下のようにします。
React
npx create-react-app sample-app --template typescript
Vue3
(コマンドを打った後に出てくる質問の Add TypeScript?でYesと答える)
npm init vue@3 sample-app
これ以降の部分は TypeScript ではなく、JavaScript でコードを書いています。
TypeScript を使う場合は適宜変換してください。
プロジェクトの起動
ローカル環境で起動する場合のコマンドです。
React
npm start
Vue3
npm run dev
起動後の初期状態は、以下のようなおなじみの画面です。
全体の構成
足し算器完成後の全体の構成は大まかに説明すると以下のような流れになっています。
React
index.js(エントリーポイント) → App.js(画面全体) → Adder.jsx(足し算器)
Vue3
main.js(エントリーポイント) → App.vue(画面全体) → Adder.vue(足し算器)
詳しくはソースコードを確認してください。
React 版はこちら
Vue3 版はこちら
ここからはメイン部分の App コンポーネントと Adder コンポーネントについて比較していきます。
App コンポーネントの比較
まず App コンポーネントの比較です。
components ディレクトリから Adder コンポーネントを取り込んでいます。
また、css ファイルもインポートしてスタイルを適用しています。
比較するとわかりやすいのですが、Vue では HTML・CSS・JavaScript の部分をはっきりと区別していることがわかります。
一方 React は HTML・CSS・JavaScript を混在させた形です。
好みの問題だと思いますがどちらも似ているので、どちらかをマスターした方であれば、もう一方に対応するのはそれほど難しくないと思います。
React
import Adder from "./components/Adder"import "./App.css"
const App = () => { return ( <div className="App"> <header> <h1>足し算器</h1> </header> <main> <Adder /> </main> </div> )}
export default App
Vue3
<script setup>import Adder from './components/Adder.vue';</script>
<template> <div className="App"> <header> <h1> 足し算器 </h1> </header> <main> <Adder /> </main> </div></template>
<style>@import "./App.css";</style>
Adder コンポーネントの比較
次に、state を含んだ Adder コンポーネントの比較です。
このコンポーネントでは、<input>
タグに入力された数字をincrease
に保存し、「足す」ボタンをクリックするとincrease
だけ、合計を表すsum
を増加させるという機能を持っています。
また、「リセット」ボタンをクリックするとsum
が 0 になります。
2 つを比較すると、細かい部分で違いがありますが、概ね同じ構造であることがわかります。
違いをまとめると以下の表のようになります。
React | Vue3 | |
---|---|---|
state の定義 | useState | ref |
state の更新 | set(State の名前) | (State の名前).value |
click イベント | onClick | @click |
change イベント | onChange | @change, @input |
変数埋め込み | { (変数) } | {{ (変数) }}, “(変数)” |
React
import React, { useState } from "react"import "./css/Adder.css"
const Adder = () => { const [sum, setSum] = useState(0) const [increase, setIncrease] = useState("1")
const add = () => { const parsed = parseInt(increase) if (isNaN(parsed)) { alert("増加量には数字を入力してください") } else if (parsed < 0) { alert("増加量には0以上の値を入力してください") } else { setSum(sum + parsed) } }
const reset = () => { setSum(0) }
const changeIncrease = e => { const value = e.target.value const parsed = parseInt(value) // 空文字か0以上の数字のみ入力可 if (value === "" || (!isNaN(parsed) && parsed >= 0)) { setIncrease(value) } else { alert("0以上の数字を入力してください") } }
return ( <div className="adder"> <h2>合計:{sum}</h2> <p> 増加量: <input type="number" value={increase} onChange={changeIncrease} /> </p> <div className="buttons"> <button onClick={add}>足す</button> <button onClick={reset}>リセット</button> </div> </div> )}
export default Adder
Vue3
<script setup>import { ref } from 'vue';
const sum = ref(0);const increase = ref('1');
const add = () => { const parsed = parseInt(increase.value); if (isNaN(parsed)) { alert('増加量には数字を入力してください'); } else if (parsed < 0) { alert('増加量には0以上の値を入力してください'); } else { sum.value += parsed; }};
const reset = () => { sum.value = 0;};
const changeIncrease = (e) => { const value = e.target.value; const parsed = parseInt(value); // 空文字か0以上の数字のみ入力可 if (value === '' || (!isNaN(parsed) && parsed >= 0)) { increase.value = value; } else { alert('0以上の数字を入力してください'); }};</script>
<template> <div className="adder"> <h2>合計:{{sum}}</h2> <p>増加量:<input type="number" :value="increase" @input="changeIncrease"/></p> <div className="buttons"> <button @click="add">足す</button> <button @click="reset">リセット</button> </div> </div></template>
<style>@import './css/Adder.css';</style>
GitHub Pages へのデプロイ
最後に、GitHub Pages へのデプロイです。
これはどちらも gh-pages を入れることで簡単にデプロイできます。
React
公式のこちらのページを参考にデプロイします。
1.package.json にhomepage
を追加する
"homepage": "https://(githubのユーザー名).github.io/sample-app",
2.npm パッケージgh-pages
をインストールし、package.json にscripts
を追加
npm install --save gh-pages
そして、package.json に以下の記述を追加
"scripts": {+ "predeploy": "npm run build",+ "deploy": "gh-pages -d build", "start": "react-scripts start",
3.デプロイコマンドを打つ
npm run deploy
Vue3
こちらのページを参考にしました。
1.vite.config.js にbase
を追加する
export default defineConfig({+ base: '/sample-app/', plugins: [vue()],
2.npm パッケージgh-pages
をインストールし、package.json にscripts
を追加
npm install --save gh-pages
そして、package.json に以下の記述を追加
"scripts": {+ "deploy": "npm run build && gh-pages -d dist", "start": "react-scripts start",
3.デプロイコマンドを打つ
npm run deploy
スポンサードリンク
まとめ
今回の記事では、Vue3 の最新の書き方を React と比較しながら紹介しました。
比較するとわかるように、細かい部分で名称やコマンドの違いがあるものの、概ね構造が同じであることがわかりました。
このため、Vue3 と React を行き来することはそれほど難しいことではない と思います。
今回は基本的な部分の比較になってしまったので、もし需要があれば詳細な部分についての比較も記事にしたいと思います。