ウェブ・開発

初心者でもわかる!Vue.js・React・Angular徹底比較 ― 3大フロントエンドフレームワークの選び方

この記事は約17分で読めます。
スポンサーリンク

ウェブ開発の世界では、ユーザー体験を支えるフロントエンド技術が年々進化しています。中でも「Vue.js」「React」「Angular」は“世界三大フロントエンドフレームワーク”と呼ばれる存在で、どれも高機能かつ広く採用されています。しかし、初めて学ぶ人にとって「どれを選べばいいの?」という疑問は尽きません。この記事では、それぞれのフレームワークの特徴を初心者にもわかりやすく解説し、簡単なサンプルコードと動作の流れを丁寧に解説します。最後には「買い物リストアプリ」を3つのフレームワークで実装し、比較しながら学べるようにしています。

スポンサーリンク

Vue.js

概要

Vue.jsは、軽量で学習コストが低いことから、初心者に最も優しいフロントエンドフレームワークの一つです。HTML、CSS、JavaScriptの基本を活かしながら、少しずつ拡張していけるのが特徴です。リアクティブ(双方向データバインディング)な仕組みを持ち、ユーザーの入力や状態の変化に応じて自動で画面を更新します。Vueの「テンプレート構文」はシンプルで、HTMLに{{ message }}のように変数を埋め込むだけで動的な表示が可能です。
また、Vueコンポーネントは単一ファイル(.vue)で管理できるため、HTML・CSS・JSが分かりやすくまとまります。中小規模サイトから企業システムまで柔軟に対応でき、特にSPA(シングルページアプリケーション)開発に強みを持っています。

サンプル

カウンターアプリ

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8" />
  <title>カウンターアプリ (Vue 3)</title>
</head>
<body>
 <div id="app">
    <h2>{{ count }}</h2>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
  <script>
  new Vue({
    el: '#app',
    data: { count: 0 },
    methods: {
      increment() { this.count++ },
      decrement() { this.count-- }
    }
  })
  </script>
</body>
</html>

コードレビュー

dataはアプリの状態(ここではcount)を保持する領域で、{{ count }}と書くとHTMLに即時反映されます。@clickはVue独自のクリックイベントディレクティブで、incrementdecrementを呼び出します。ボタンを押すたびに内部のcountが変わり、Vueが自動的に再描画してくれるため、DOM操作を明示的に書く必要がありません。これがVueの「リアクティブな魔法」です。

Vue.js
Vue.js - The Progressive JavaScript Framework

React

概要

ReactはFacebook(現Meta)が開発したフレームワークで、コンポーネント志向の設計が特徴です。ユーザーインターフェイスを「部品」として再利用できる構造を持ち、大規模アプリケーションにも適しています。JSX(JavaScript + XML)という構文を使い、HTMLのような記述で動的要素を組み立てられます。
Reactの考え方は「状態(state)」を中心に据える点にあります。UIは状態の結果であるという発想で、setStateによる更新が行われると、自動的に仮想DOM(Virtual DOM)が差分描画を行い、効率的に画面を更新します。これにより、大量のUI要素を持つアプリでも高速に動作します。

サンプル

カウンターアプリ

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8" />
  <title>カウンターアプリ (React)</title>
</head>
<body>
  <div id="root"></div>
  <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

  <script type="text/babel">
  function Counter() {
    const [count, setCount] = React.useState(0);

    return (
      <div>
        <h2>{count}</h2>
        <button onClick={() => setCount(count + 1)}>+</button>
        <button onClick={() => setCount(count - 1)}>-</button>
      </div>
    );
  }

  ReactDOM.render(<Counter />, document.getElementById('root'));
  </script>
</body>
</html>

コードレビュー

useStateはReactのフックで、状態変数countと更新関数setCountを定義します。ボタン押下時にsetCountを呼ぶと再描画が行われ、画面上のcountが変化します。仮想DOMにより効率的に必要部分だけが更新されるため、高速でスムーズな動作を実現します。Reactは関数型アプローチを採用しており、データの流れが明確なのも魅力です。

React
React is the library for web and native user interfaces. Build user interfaces out of individual pieces called component...

Angular

概要

AngularはGoogleが開発したフルスタックなフレームワークで、他の2つと異なりTypeScriptをベースとしています。DI(依存性注入)やルーティング、フォームバリデーションなど、Webアプリに必要な機能が標準で揃っており、企業システムや大規模開発に適しています。
AngularはMVC(Model-View-Controller)思想を継承し、データの流れを明確に分離しています。また、双方向データバインディングによりユーザーの操作とモデルの状態が即時同期され、整合性を保ちやすい構造です。やや学習コストは高いものの、一度慣れれば開発効率が非常に高まります。

サンプル

カウンターアプリ

<!DOCTYPE html>
<html lang="ja">
  <head>
    <title>カウンターアプリ (Angular)</title>
    <script src="https://unpkg.com/@angular/core@17/bundles/core.umd.js"></script>
    <script src="https://unpkg.com/@angular/platform-browser-dynamic@17/bundles/platform-browser-dynamic.umd.js"></script>
    <script src="https://unpkg.com/@angular/compiler@17/bundles/compiler.umd.js"></script>
  </head>
  <body>
    <app-root>読み込み中...</app-root>

    <script type="text/javascript">
      const { Component, NgModule } = ng.core;
      const { BrowserModule } = ng.platformBrowserDynamic;

      @Component({
        selector: 'app-root',
        template: `
          <h2>{{count}}</h2>
          <button (click)="inc()">+</button>
          <button (click)="dec()">-</button>
        `
      })
      class AppComponent {
        count = 0;
        inc() { this.count++; }
        dec() { this.count--; }
      }

      @NgModule({
        declarations: [AppComponent],
        imports: [BrowserModule],
        bootstrap: [AppComponent]
      })
      class AppModule {}

      ng.platformBrowserDynamic.platformBrowserDynamic().bootstrapModule(AppModule);
    </script>
  </body>
</html>

コードレビュー

@Componentはコンポーネントを定義するデコレーターで、テンプレート内の{{count}}とクラス変数が双方向で結びつきます。(click)="inc()"のようなイベントバインディングで、クリック時にメソッドを実行します。Angularは内部で依存関係やモジュールを管理しているため、コード量は多いものの、堅牢な構造で大規模開発に最適です。

Angular
The web development framework for building modern apps.

各フレームワークの比較表

項目Vue.jsReactAngular
開発元Evan You(元Google)Meta(旧Facebook)Google
使用言語JavaScriptJavaScript(+JSX)TypeScript
学習難易度
特徴シンプルで導入容易コンポーネント志向・仮想DOMフルスタック構成・大規模対応
用途小〜中規模アプリ中〜大規模アプリ大規模・業務アプリ
主な構文テンプレート構文JSXTypeScriptデコレーター

応用版(買い物リスト)

Vue.js版

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8" />
  <title>買い物リストアプリ (Vue.js)</title>
</head>
<body>
<div id="app">
  <input v-model="item" placeholder="商品を入力">
  <button @click="addItem">追加</button>
  <ul>
    <li v-for="(todo, index) in todos">
      <span :style="{textDecoration: todo.done ? 'line-through' : 'none'}">{{ todo.text }}</span>
      <button @click="todo.done = !todo.done">済</button>
      <button @click="removeItem(index)">削除</button>
    </li>
  </ul>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script>
new Vue({
  el: '#app',
  data: { item: '', todos: [] },
  methods: {
    addItem() {
      if (this.item) {
        this.todos.push({ text: this.item, done: false });
        this.item = '';
      }
    },
    removeItem(i) { this.todos.splice(i, 1); }
  }
})
</script>
</body>
</html>

React版

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8" />
  <title>買い物リストアプリ (React)</title>
</head>
<body>
<div id="root"></div>
<script src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

<script type="text/babel">
function App() {
  const [item, setItem] = React.useState('');
  const [todos, setTodos] = React.useState([]);

  const addItem = () => {
    if (item) {
      setTodos([...todos, { text: item, done: false }]);
      setItem('');
    }
  };

  const toggleDone = index => {
    const newTodos = [...todos];
    newTodos[index].done = !newTodos[index].done;
    setTodos(newTodos);
  };

  const removeItem = index => setTodos(todos.filter((_, i) => i !== index));

  return (
    <div>
      <input value={item} onChange={e => setItem(e.target.value)} placeholder="商品を入力" />
      <button onClick={addItem}>追加</button>
      <ul>
        {todos.map((t, i) => (
          <li key={i}>
            <span style={{ textDecoration: t.done ? 'line-through' : 'none' }}>{t.text}</span>
            <button onClick={() => toggleDone(i)}>済</button>
            <button onClick={() => removeItem(i)}>削除</button>
          </li>
        ))}
      </ul>
    </div>
  );
}
ReactDOM.render(<App />, document.getElementById('root'));
</script>
</body>
</html>

Angular版

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>買い物リストアプリ (Angular)</title>
    <script src="https://unpkg.com/@angular/core@17/bundles/core.umd.js"></script>
    <script src="https://unpkg.com/@angular/platform-browser-dynamic@17/bundles/platform-browser-dynamic.umd.js"></script>
    <script src="https://unpkg.com/@angular/compiler@17/bundles/compiler.umd.js"></script>
  </head>
  <body>
    <app-root>読み込み中...</app-root>
    <script type="text/javascript">
      const { Component, NgModule } = ng.core;
      const { BrowserModule } = ng.platformBrowserDynamic;

      @Component({
        selector: 'app-root',
        template: `
          <input [(ngModel)]="item" placeholder="商品を入力">
          <button (click)="addItem()">追加</button>
          <ul>
            <li *ngFor="let todo of todos; let i = index">
              <span [style.textDecoration]="todo.done ? 'line-through' : 'none'">{{ todo.text }}</span>
              <button (click)="toggleDone(i)">済</button>
              <button (click)="removeItem(i)">削除</button>
            </li>
          </ul>
        `
      })
      class AppComponent {
        item = '';
        todos = [];
        addItem() {
          if (this.item) {
            this.todos.push({ text: this.item, done: false });
            this.item = '';
          }
        }
        toggleDone(i) { this.todos[i].done = !this.todos[i].done; }
        removeItem(i) { this.todos.splice(i, 1); }
      }

      @NgModule({
        declarations: [AppComponent],
        imports: [BrowserModule],
        bootstrap: [AppComponent]
      })
      class AppModule {}

      ng.platformBrowserDynamic.platformBrowserDynamic().bootstrapModule(AppModule);
    </script>
  </body>
</html>

総評

Vue.jsはとにかく「やってみよう」と思った瞬間に動かせる手軽さが魅力で、HTML感覚で始めたい人に最適です。Reactはデータの流れと状態管理の思想が明確で、アプリ開発の本質を学びたい人におすすめ。Angularはやや難しいですが、企業システムやチーム開発を見据えるなら将来性が高い選択です。
最初の一歩を踏み出すなら、まずVue.jsで「動く楽しさ」を感じ、その後Reactで「設計の美しさ」に触れると、自然にAngularの「体系的な強さ」も理解できるようになります。どのフレームワークも目的や規模に応じて正解になり得ます。大切なのは「自分の作りたいもの」に合った道を選ぶことです。

スポンサーリンク
ウェブ・開発
フォローしてね
スポンサーリンク

コメント

タイトルとURLをコピーしました