【Vue 3】React 経験者のための Vue 入門 - template・ref・props を React と比較して理解する

PUBLISHED 2026-02-07

React の経験がある方が Vue を学ぶ際、構文の違いに戸惑うことがあります。しかし、Vue と React は根本的な概念が似ており、対応関係を理解すればスムーズに移行できます。

この記事では、Vue 3 の Composition API(<script setup>)を中心に、React との対応表を交えながら基本構文を解説します。

Vue コンポーネントの構造

Vue のコンポーネントは 3 つのブロック で構成されます。

<template>
  <!-- HTML構造を記述する場所 -->
  <div>
    <h1>{{ message }}</h1>
    <button @click="count++">クリック: {{ count }}</button>
  </div>
</template>

<script setup>
// JavaScriptロジックを記述する場所
import { ref } from 'vue'

const message = ref('こんにちは')
const count = ref(0)
</script>

<style scoped>
/* CSSスタイルを記述する場所 */
h1 {
  color: blue;
}
</style>
ブロック役割React での対応
<template>何を表示するか(HTML 構造)JSX(return 文の中身)
<script>どう動くか(ロジック・データ)コンポーネント関数の本体
<style>どう見えるか(装飾)CSS Modules / styled-components
💡 template とは

template は「テンプレート(ひな形)」の意味で、コンポーネントがレンダリングする HTML の設計図です。React では JSX として JavaScript の中に HTML を書きますが、Vue では HTML 側に専用のディレクティブ(v-*@:)を付けるアプローチです。

データ表示とディレクティブ

テキスト表示

Vue ではマスタッシュ構文 {{ }} でデータを表示します。

✅ Vue

{"{{ message }}"}

❌ React

{"{message}"}

ループ(v-for = map)

React の .map() に対応するのが Vue の v-for です。

<!-- Vue -->
<template>
  <ul>
    <li v-for="item in items" :key="item.id">
      {{ item.name }}
    </li>
  </ul>
</template>
// React
return (
  <ul>
    {items.map(item => (
      <li key={item.id}>{item.name}</li>
    ))}
  </ul>
)

条件分岐(v-if = && / 三項演算子)

<!-- Vue -->
<div v-if="show">表示する</div>
<div v-else>非表示</div>
// React
{show ? <div>表示する</div> : <div>非表示</div>}

ディレクティブ対応表

機能ReactVue
テキスト表示{message}{{ message }}
HTML 挿入dangerouslySetInnerHTMLv-html
ループ.map()v-for
条件表示{show && <div>...</div>}v-if
条件切替三項演算子v-if / v-else
非表示(DOM 残す)自前で実装v-show

イベントハンドリング

Vue では @ プレフィックスでイベントを記述します。

機能ReactVue
クリックonClick={handler}@click="handler"
入力変更onChange={handler}@change="handler"
フォーム送信onSubmit={handler}@submit="handler"
preventDefaulte.preventDefault()@submit.prevent="handler"

Vue の イベント修飾子.prevent.stop.once など)を使うと、e.preventDefault() のようなボイラープレートが不要になります。

<!-- Vue: 修飾子で簡潔に書ける -->
<form @submit.prevent="handleSubmit">
  <button type="submit">送信</button>
</form>

属性バインディング

動的な属性値には : プレフィックスを使います。

機能ReactVue
動的属性src={url}:src="url"
クラスclassName={cls}:class="cls"
スタイルstyle={{ color: 'red' }}:style="{ color: 'red' }"

状態管理: ref と reactive

ref(プリミティブ値向け)

React の useState に相当するのが Vue の ref です。

<script setup>
import { ref } from 'vue'

// React: const [count, setCount] = useState(0)
const count = ref(0)

function increment() {
  // script 内では .value が必要
  count.value++
}
</script>

<template>
  <!-- template 内では .value は不要 -->
  <button @click="increment">{{ count }}</button>
</template>
💡 ref の特徴

Vue はセッター関数が不要で直接代入できるのが大きな違いです。count.value++ だけで状態が更新され、template が自動的に再レンダリングされます。

reactive(オブジェクト/配列向け)

オブジェクトや配列には reactive も使えます。

<script setup>
import { reactive } from 'vue'

// React: const [form, setForm] = useState({ name: '', age: 0 })
const form = reactive({
  name: '',
  age: 0,
})

// 直接変更できる(setForm のようなセッター不要)
form.name = '太郎'
form.age = 25
</script>

<template>
  <input v-model="form.name" />
  <input v-model.number="form.age" />
</template>

ref vs reactive の使い分け

refreactive
対象プリミティブ値(文字列、数値、真偽値)オブジェクト・配列
アクセスcount.value(script 内)form.name(そのまま)
再代入count.value = 10 OKform = {...} NG(参照が切れる)
📌

迷ったら ref だけ使えば問題ありません。ref はオブジェクトにも使えます。reactive はネストしたオブジェクトを .value なしでアクセスしたい場合に便利です。

状態管理の対応表

機能ReactVue
状態定義const [count, setCount] = useState(0)const count = ref(0)
値の更新setCount(count + 1)count.value++
算出値useMemo(() => ..., [deps])computed(() => ...)
副作用useEffect(() => ..., [deps])watch(source, callback)
マウント時useEffect(() => ..., [])onMounted(() => ...)

双方向バインディング: v-model

Vue 特有の機能として v-model があります。フォーム入力と状態を自動的に同期します。

✅ Vue(v-model で簡潔)
<input v-model="name" />
❌ React(手動で同期)
<input
  value={name}
  onChange={e => setName(e.target.value)}
/>

Props と Emit: コンポーネント間の通信

Props(親 → 子)

<!-- 親コンポーネント -->
<template>
  <UserCard name="太郎" :age="25" />
</template>
<!-- 子コンポーネント(UserCard.vue) -->
<script setup>
const props = defineProps({
  name: String,
  age: Number,
})
</script>

<template>
  <div>{{ name }}({{ age }}歳)</div>
</template>

TypeScript を使う場合

<script setup lang="ts">
// 型指定
const props = defineProps<{
  name: string
  age?: number
}>()

// デフォルト値をつけたい場合
const props = withDefaults(defineProps<{
  name: string
  age?: number
}>(), {
  age: 20,
})
</script>

Emit(子 → 親)

React で「関数を props で渡す」パターンに対応するのが Vue の emit です。

<!-- 親 -->
<template>
  <Child @delete="handleDelete" />
</template>
<!-- 子 -->
<script setup>
const emit = defineEmits(['delete'])

function remove(id) {
  emit('delete', id)
}
</script>

コンポーネント通信の対応表

機能ReactVue
引数の受け取りfunction Comp({ name })defineProps({ name: String })
親への通知props.onChange(value)emit('change', value)
children{ children }<slot />
📌 Vue の基本の流れ

データは props で下へ、イベントは emit で上へ が Vue の基本的なデータフローです。React の「単方向データフロー」と同じ考え方です。

レンダリングの最適化

Vue は自動追跡

Vue はリアクティブな依存関係を自動追跡するため、必要な部分だけが再レンダリングされます。React のように memouseCallback を手動で指定する必要が少ないのが特徴です。

手段説明
コンポーネント分割状態を持つ部分を小さいコンポーネントに分離
v-memo条件が変わるまで再レンダリングをスキップ
v-once初回のみレンダリング、以降は更新しない
shallowRefネストしたオブジェクトの深い変更を追跡しない
computed依存値が変わった時だけ再計算
<!-- v-once: 一度だけ描画(静的コンテンツ向け) -->
<h1 v-once>{{ title }}</h1>

<!-- v-memo: 指定した値が変わるまで更新しない -->
<div v-memo="[itemId]">
  {{ heavyCalculation }}
</div>
✅ Vue(自動追跡)

自動で必要な部分だけ更新。大抵はコンポーネント分割だけで十分

❌ React(手動制御)

親の再レンダリングで子も全部再レンダリング。React.memo / useMemo / useCallback で手動制御

Options API と Composition API

Vue には 2 つの書き方 があります。

API特徴React との類似度
Composition API(<script setup>関数ベース。Vue 3 推奨React Hooks に近い
Options API(export default {}オブジェクトベース。Vue 2 時代の書き方クラスコンポーネントに近い

現在は Composition API が推奨されていますが、既存のプロジェクトでは Options API のコードも見かけます。

// Options API(古い書き方)
export default {
  props: ["page"],
  computed: {
    fullName() {
      return this.firstName + ' ' + this.lastName
    }
  },
  methods: {
    greet() {
      console.log('Hello')
    }
  }
}
<!-- Composition API(推奨) -->
<script setup>
import { computed } from 'vue'

const props = defineProps({ page: Object })

const fullName = computed(() => firstName.value + ' ' + lastName.value)

function greet() {
  console.log('Hello')
}
</script>

全体の対応まとめ

React → Vue 対応チェックリスト
  • JSX → template + ディレクティブ(v-for, v-if, @click, :src)
  • useState → ref / reactive
  • useMemo → computed
  • useEffect → watch / onMounted
  • props(関数渡し) → emit
  • children → slot
  • v-model Vue 独自の双方向バインディング
  • イベント修飾子 .prevent, .stop など Vue 独自の省略記法

参考文献

まとめ

React 経験者が Vue を学ぶ際のポイントは以下の 3 点です。

  1. template + ディレクティブ が React の JSX に対応する。HTML 側に v-forv-if@click を付けるアプローチ
  2. ref / reactiveuseState に対応する。セッター関数不要で直接代入できる
  3. props は下へ、emit は上へ が基本のデータフロー。React の「関数を props で渡す」パターンが Vue では emit になる

Vue はリアクティブシステムが自動追跡するため、React に比べてレンダリング最適化の手動作業が少ないのが特徴です。

CATEGORY
TAGS
円