注意
- 2025/03 時点での比較です
初めて記事を書くので、マークダウン記法で遊んでます
背景
入社してもうすぐ1年が経ち、この1年でVue.js、React両方に触れてきました。
そこで、知識の整理も兼ねて記事としてアウトプットすることにしました。
※全体比較を一記事にまとめるほどの構成力は持っていないので、概念・機能単位で比較記事を作成していく予定です。
自己紹介
初めに、自己紹介をしておこうと思います!
- エンジニアもうすぐ一年(新卒入社、研修3ヶ月・開発業務9ヶ月)
- 業務ではフロントエンド開発(Vue.js)
- 社内の勉強会などで他技術にも触れている
- それぞれの使用歴
- Vue.js:1年(業務)
- React:半年(社内勉強会)
立ち位置はVue寄り(好み)
という感じで、フロントエンドエンジニア1年生です
簡単比較
始めに、書き方や機能など基本的な部分を簡単に比較してみました。
項目 | Vue.js | React |
---|---|---|
書き方(テンプレート) | HTMLライクで直感的な構文 (.vue) | JSX/TSX |
コンポーネント | 単一ファイルコンポーネント(SFC) | JavaScript/TypeScript関数 |
データバインディング | 双方向データバインディング | 単方向データバインディング |
状態管理1 | ref, reactive (Pinia, Vuex) | useState(Redux, Zustand) |
ライフサイクル管理 | ライフサイクルフック(onMounted, updated など) | useEffect |
スタイリング | Scoped CSSや外部CSS | CSS-in-JSや外部CSS |
学習コスト | 低~中(テンプレート構文が直感的で学習しやすい) | 中~高(JSXや状態管理の学習が必要) |
※公式ドキュメントに準拠しているつもりですが、分かりやすさ・自分の理解を文章にするなどを優先しているため、ツッコミどころが多いかもしれません。
コンポーネントとは?
Vue.jsとReactに共通する重要な概念で、ユーザーインターフェース(UI)を構成する「再利用可能な部品」を指します。
例えば、ボタンや入力フォーム
などの最小単位コンポーネント、それらを組み合わせた登録画面コンポーネントのようなイメージです。この関係は、子コンポーネントと親コンポーネントと言います。
コンポーネント設計のメリット・デメリット
コンポーネントを意識した設計は、以下のメリットとデメリットがあります。
メリット
- 再利用可能
- コンポーネント単位で設計、開発、テストができる(保守性の向上)
- コードが整理され、可読性が高い
綺麗にコンポーネント分割すると気持ちいい
デメリット
- 再利用性を考慮した初期設計コストが高い
- 大規模になると、親子の依存関係が複雑になりやすい
基本構文・コンポーネントの比較
やっと本編です
このセクションでは、VueとReactそれぞれの基本的な書き方とコンポーネントの単位・呼び出し方について説明します
Vue.js
基本構文
Vueでは、テンプレート(HTML)、ロジック(JavaScript)、スタイル(CSS)を1ファイルに統合した形で記述するのが基本です。
コードを用いた説明の方が理解しやすいため、以下にサンプルコードを示します。
<template>
<p>{{ message }}</p>
</template>
<script setup>
const message = "Hello, world"
</script>
<style scoped>
p {
color: blue;
}
</style>
説明:
コードから分かる通り、HTMLライクに記述できます。アプリケーション画面とそれぞれのブロックの関係は以下の通りです。
-
templete
- アプリケーション画面の大まかな「見た目」を定義します
- ユーザーが目にする、テキストやボタンなどの要素をここに記述します
-
script
- アプリケーション画面の「振る舞い」を定義します
- イベント処理、データの管理、API呼び出しなど、画面がどのように動作するかをここに記述します
-
style
- アプリケーション画面の細かいデザインを定義します
- templateブロックの要素に対して、配置や色、フォントなどのスタイルを指定します
補足として、scriptブロックの書き方はComposition APIと言います。
ここの記述には2通りのAPIスタイルがあり、Option APIという書き方もあります。
Option APIで書き換えたscript
<script>
export default {
data() {
return {
message: "Hello, world"
};
}
};
</script>
コンポーネント
基本構文で説明したコード全体が入った.vue
ファイルが一つのコンポーネントです。これを単一ファイルコンポーネント(SFC) と呼びます。
先ほどのコードをコンポーネントとして呼び出すコードは、以下になります。
<template>
<div>
<h1>親コンポーネント</h1>
<ChildComponent />
</div>
</template>
<script setup>
import ChildComponent from './ChildComponent.vue';
</script>
ChildComponent.vue
<template>
<p>{{ message }}</p>
</template>
<script setup>
const message = "Hello, world";
</script>
<style scoped>
p {
color: blue;
}
</style>
説明:
正直見たままで、親コンポーネント側scriptブロックで、子コンポーネントをインポートして、templeteブロックで使用しています。
これで子コンポーネントが呼び出され、そのtempleteブロックが表示されます。
React
基本構文
Reactでは、JSX(JavaScript XML)という形式で、JavaScriptコード内にHTMLを書くスタイルが基本です2。
こちらもコードでの説明の方が理解しやすいため、以下にサンプルコードを示します。
export default function ChildComponent() {
const message = "Hello, world";
return <p style={{ color: "blue" }}>{message}</p>;
}
説明:
このコードは、非常にJavaScriptライクです。return内にHTML/CSS(見た目)を記述し、関数内のreturn以前の部分にアプリケーションの動作(振る舞い)を記述しています。
補足として、コンポーネントの書き方はfunction
(関数宣言)とアロー関数 の2つのスタイルがあります。
この記事は、公式ドキュメントに準拠してfunction
で記述しています。
アロー関数
const ChildComponent = () => {
const message = "Hello, world";
return <p style={{ color: "blue" }}>{message}</p>;
};
export default ChildComponent;
コンポーネント
基本構文で示したJavaScript関数が1つのコンポーネントです。普通のJavaScriptとの違いは以下です。
- 関数名の最初は必ず大文字
- JSX マークアップを
return
する
コンポーネントを呼び出すコードは、以下になります。
import ChildComponent from "./child";
export default function ParentComponent() {
return (
<div>
<h1>親コンポーネント</h1>
<ChildComponent />
</div>
);
}
説明:
親コンポーネント側ファイルで、子コンポーネントをインポートして、親コンポーネントのreturn内のJSX マークアップで使用しています。
これで子コンポーネントが呼び出され、表示されます。
同じファイル内で定義している場合は、そのまま使用できます。
同一ファイルで定義
function ChildComponent() {
const message = "Hello, world";
return <p style={{ color: "blue" }}>{message}</p>;
}
export default function ParentComponent() {
return (
<div>
<h1>親コンポーネント</h1>
<ChildComponent />
</div>
);
}
まとめ
書くのが楽なので箇条書き
- 普段触るのが、「Nuxt(Composition API) × TypeScript」「Next.js × TSX」なので、元々のVue、Reactとはそこそこ違って比較が結構大変だった
- 初めて記事を書いたので色々手探りだったが、知識整理・説明のために公式ドキュメントを読む、マークダウン記法で遊ぶなど、いい経験になった気がする
参考にした記事
基本公式ドキュメントに準拠で、比較記事のイメージの参考にしました。