はじめに
この記事ではReactとVue3を比較しながら、Reactを迅速に習得するためのガイドを提供します。
• コンポーネント
• JSX
• インターポーラシオン
• データ通信
• レンダリング
• イベント
• ステート
コンポーネント
「コンポーネント」という言葉を初めて聞いた時は抽象的でしたが、実際には特定の機能を持つUIの集まりです。例えば、ページを MyHeader、MyMain、MyFooter の3つのコンポーネントに分けることができます。例えば、他のページの下部に表示されるものは同じであると仮定すると(これは一般的です)、他のインターフェースでMyFooterコンポーネントを適用することができます。その後の変更も一度だけ変更する必要があります。
Vue:
<MyHeader />
<MyMain />
<MyFooter />
React:
<MyHeader />
<MyMain />
<MyFooter />
JSX
コンポーネントの本質はJS関数です。MyHeaderコンポーネントを例として考えてみましょう:
Vue:
// MyHeader.ts
export default {
template: '<div>MyHeader</div>',
};
// SFC
// MyHeader.vue
<template>
<divMyHeader</div>
</template>
React:
// MyHeader.tsx
export default function MyHeader() {
return <div>MyHeader</div>;
}
ReactではHTMLタグを返すことができますが、この文法はJSXと呼ばれています。これは以下に等しいです:
React.createElement('div', null, 'MyHeader');
VueでもJSX構文がサポートされています(プラグイン:@vitejs/plugin-vue-jsxを使用)。
// MyHeader.tsx
import { defineComponent } from 'vue';
export const MyHeader = defineComponent({
setup() {
return () => <div>MyHeader</div>;
}
})
インターポーレーション
Vueでは、インターポーレーションは二重波括弧で表されますが、Reactでは単一の波括弧を使用します。
Vue:
<h1>Hello, {{ msg }}.</h1>
React:
<h1>Hello, {msg}.</h1>
データ通信は値の伝達とコンポーネントの伝達に分けられていますが、どちらも外部からの伝達です。
値の伝達
Vue:
// Parent Component
<Coding who="me" />
<Coding who="you" />
<Coding who="them" />
// Coding.vue
<script setup>
defineProps(['who']);
</script>
<template>
<div>Coding for {{ who }}.</div>
</template>
React:
// Parent Component
<Coding who={'me'} />
<Coding who={'you'} />
<Coding who={'them'} />
// Coding.tsx
export default function Coding(props: { who: string }) {
return <div>Coding for {props.who}.</div>;
}
5.2 コンポーネントの伝達
スロットを通じてコンポーネントを伝達しますが、これはゲーム機のカードスロットやコンピュータの周辺インターフェースのようなものです。
Vue:
<MyCard>This is my card.</MyCard>
<MyCard>
<Coding who="boss" />
</MyCard>
// MyCard.tsx
<template>
<div :style="{ border: '1px solid #000' }">
<slot></slot>
</div>
</template>
React:
<MyCard>This is my card.</MyCard>
<MyCard>
<Coding who={'boss'} />
</MyCard>
// MyCard.tsx
export default function MyCard({ children }: { children: React.ReactNode }) {
return <div style={{ border: '1px solid000' }}>{children}</div>;
}
** リストのレンダリング**
Vue:
const list = [
{ id: 1, name: '🍎', price: 6 },
{ id: 2, name: '🍌', price: 3 },
{ id: 3, name: '🍐', price: 5 },
];
<ul>
<li v-for="item in list" :key="item.id">
{{ item.name }}-{{ item.price }}
</li>
</ul>
React:
<ul>
{list.map((item) => (
<li key={item.id}>
{item.name}-{item.price}
</li>
))}
</ul>
6.2 条件付きレンダリング
Vue:
const visible = false;
<div>
<p v-if="visible"> show </p>
<p v-else> hidden </p>
</div>
React:
const visible = false;
<div>
{visible ? <p>show</p> : <p> hidden</p> }
</div>
イベント
ウェブページでは多くのインタラクション機能を実現できますが、さまざまなイベントを活用します:クリックイベント、マウス移動イベント、キーボードクリックイベントなど…
Vue:
<form
@submit="
(e) => {
e.preventDefault();
console.log('submit');
}
">
<input @change="(e) => console.log('something change:', e.target.value)" />
<button @click="() => console.log('clicked')"> sumbit </button>
</form>
React:
<form
onSubmit={(e) => {
e.preventDefault();
console.log('submit');
}}>
<input onChange={(e) => console.log('something change:', e.target.value)} />
<button onClick={() => console.log('clicked')}>sumbit </button>
</form>
ステート
Vueでは、ref(リアクティブ参照)、reactive()(リアクティブオブジェクト)というメソッドを使用してステートを管理しますが、ReactではuseStateメソッドを使用します。
Vue:
import { ref } from 'vue';
const count = ref(0);
<p> {{ count }}</p>
<button @click="() => count++"+1</button>
React:
import { useState } from 'react';
const [count, setCount] = useState(0);
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
ユーザーがボタンをクリックすると、setCountがトリガーされます。
ステートcountを更新します。
{count}は新しいステートを読み取ります。