なぜVueを始めるべきか:文法
前置き
前回の記事ではデータバインディングについて
その中でもコンポーネントとコンポーネント間のデータバインディングについて詳細に話しました。
今回は実際プログラミングで使う文法
について比較しようかと思っています。
React
も同じですが、Vue
も基本的にJavaScriptベースで作られたものなので
基本的なJavaScriptはVue内でも使えます。
ただ、各ライブラリー・フレームワークによってコーディングスタイルが違います。
特にフレームワークであるVue
はレガシーJavaScriptよりはVueで提案している
文法を使うほうが良いでしょう。
比較対象について
今回比較対象は以下の通り
簡単なif
とfor
からライフサイクル関連関数まで話しようかと思っています。
基本的にReactはJavaScriptに近いほで
Vueの場合はVueで提供している文法があります。
- リスト
if
,for
,props渡し
、データバインディング
各コードは以下の通りです。
コードとしては少し違うところがありますが、同じ機能になります。
例コードについて
フロントエンドで良く使うIF文の例は一部のUI(コンポーネント)を非活性にするところかと思います。
例えばボタンを押下したらポップアップ表示されたり、初期ページのデータを取得する前にローディング画面を表示する時に良く使います。
今回は簡単な例を用意しました。
テキストボックスがあり、入力すると三つのボックスに入力した内容が表示されます。
さらに3秒ごとに三つのボックスが表示・非表示されるコードになります。
全体なコードは以下のリンクで確認可能です。
IF
まずはIF文です。
React: IF文
・・・
export default function App() {
・・・
// 表示・非表示変数
const [isShowBlock, setIsShowBlock] = useState(true);
・・・
useEffect(() => {
const intervalId = setInterval(() => {
// 3秒ごとに表示・非表示変数の値を反転する
setIsShowBlock((prev) => !prev);
}, 3000);
return () => clearInterval(intervalId);
}, []);
return (
<div className="App">
<input value={input} onChange={(e) => setInput(e.target.value)} />
<!-- 表示・非表示変数がTrueなら表示、Falseなら非表示する -->
{isShowBlock && (
<div className="Wapper">
{componentName.map((value, index) => (
<SimpleArea input={input} name={value} key={index} />
))}
</div>
)}
</div>
);
}
ポイントになるコードは{isShowBlock &&
と言うどころです。
Reactの場合、JavaScriptと同様です。
HTML(又JSX)内部ではIF文を使えないため、他の方法を使うしかないです。
一番簡潔な使い方は例見たいに**論理演算子(&&)**を使う方法です。
それ以外は条件 (三項) 演算子
<!-- 表示・非表示変数がTrueなら表示、Falseなら非表示する -->
{isShowBlock ? (
<div className="Wapper">
{componentName.map((value, index) => (
<SimpleArea input={input} name={value} key={index} />
)) : null}
</div>
)}
この部分をそのまま関数化する方法があります。
function MyComponent({ isShowBlock }) {
if (isShowBlock) {
return (
<div className="Wapper">
{componentName.map((value, index) => (
<SimpleArea input={input} name={value} key={index} />
))}
</div>
);
} else {
return null;
}
}
つまり、Reactの場合JavaScriptと同様のため、
JavaScriptに慣れてないと上手く使うことが難しいです。
いろんな方法があるため、人によって使い方がバラバラになる可能性もあります。
なのでプロジェクト内で標準を決める必要があります。
Vue: IF文
<template>
<div>
<input v-model="input" />
<!-- 表示・非表示変数がTrueなら表示、Falseなら非表示する -->
<div class="Wapper" v-if="isShowBlock">
<SimpleArea v-for="(item, i) in componentName" :key="i" :input="input" :name="item" />
</div>
</div>
</template>
<script>
・・・
export default {
・・・
data() {
return {
・・・
// 表示・非表示変数
isShowBlock: true,
};
},
・・・
}
</script>
Vueの場合は、Vue内部でv-if
と言うキーワードが存在するため
タグ内に条件式をv-if
を入れるだけで終わりです。
For
React: For文
・・・
export default function App() {
・・・
const componentName = ["component1", "component2", "component3"];
・・・
return (
<div className="App">
<input value={input} onChange={(e) => setInput(e.target.value)} />
{isShowBlock && (
<div className="Wapper">
{componentName.map((value, index) => (
<SimpleArea input={input} name={value} key={index} />
))}
</div>
)}
</div>
);
}
キーワードはcomponentName
と言う配列とmap()
関数になります。
Reactの場合、IF文と同様な理由で一般的なfor文は使えません。
一番簡潔な使い方はMap
関数を使う方法です。
Vue: For文
<template>
<div>
<input v-model="input" />
<div class="Wapper" v-if="isShowBlock">
<SimpleArea v-for="(item, i) in componentName" :key="i" :input="input" :name="item" />
</div>
</div>
</template>
<script>
import SimpleArea from "./components/SimpleArea.vue";
export default {
・・・
}
</script>
キーワードは<SimpleArea>
コンポーネント内のv-for
になります。
Vueの場合はv-for
内に数式を入力することで終わりです。
Props渡し, データバインディング
React : Props渡し
・・・
// inputとnameをpropsとして定義
const SimpleArea = ({ input, name }) => {
return (
<div className="SimplePanel">
<div className="SimpleName">{name}</div>
<div className="SimpleArea">{input}</div>
</div>
);
};
export default function App() {
・・・
return (
<div className="App">
<input value={input} onChange={(e) => setInput(e.target.value)} />
{isShowBlock && (
<div className="Wapper">
{componentName.map((value, index) => (
// input,nameをPropsとして設定
<SimpleArea input={input} name={value} key={index} />
))}
</div>
)}
</div>
);
}
Reactの場合はPropsを受けているconst SimpleArea = ({ input, name })
と
<SimpleArea input={input} name={value} key={index} />
部分がキーワードになります。
Propsを受ける側はパラメーターとして、渡す側は属性として設定します。
React : データバインディング
・・・
// inputとnameをpropsとして定義
const SimpleArea = ({ input, name }) => {
return (
<div className="SimplePanel">
<div className="SimpleName">{name}</div>
<div className="SimpleArea">{input}</div>
</div>
);
};
export default function App() {
・・・
return (
<div className="App">
//単方向データバインディングのため、onChangeが必要
<input value={input} onChange={(e) => setInput(e.target.value)} />
{isShowBlock && (
<div className="Wapper">
{componentName.map((value, index) => (
// input,nameをPropsとして設定
<SimpleArea input={input} name={value} key={index} />
))}
</div>
)}
</div>
);
}
以前の記事でも説明した通り、
Reactの場合は単方向データバインディングを採用しているので
<input value={input} onChange={(e) => setInput(e.target.value)} />
上のようにonChange内に追加でイベントトリガーを設定する必要があります。
Vue: Props渡し
<template>
<div class="SimplePanel">
<div class="SimpleName">{{ name }}</div>
<div class="SimpleArea">{{ input }}</div>
</div>
</template>
<script>
export default {
name: 'SimpleArea',
// inputとnameをpropsとして定義
props: {
name: String,
input: String,
}
}
</script>
<template>
<div>
// v-modeキーワードで双方向データバインディング
<input v-model="input" />
<div class="Wapper" v-if="isShowBlock">
// inputとnameをpropsとして設定
<SimpleArea v-for="(item, i) in componentName" :key="i" :input="input" :name="item" />
</div>
</div>
</template>
<script>
・・・
export default {
・・・
data() {
return {
input: "",
componentName: ["component1", "component2", "component3"],
isShowBlock: true,
};
},
・・・
}
</script>
VueもReactとほぼ同じです。
<SimpleArea v-for="(item, i) in componentName" :key="i" :input="input" :name="item" />
渡す側は頭に:
キーワード付けてProps設定します。
<script>
export default {
name: 'SimpleArea',
// inputとnameをpropsとして定義
props: {
name: String,
input: String,
}
}
</script>
受ける側は<script>~</script>
内部のprops
内にProps名とタイプを定義します。
Vue: データバインディング
<template>
<div class="SimplePanel">
<div class="SimpleName">{{ name }}</div>
<div class="SimpleArea">{{ input }}</div>
</div>
</template>
<script>
export default {
name: 'SimpleArea',
// inputとnameをpropsとして定義
props: {
name: String,
input: String,
}
}
</script>
<template>
<div>
// v-modeキーワードで双方向データバインディング
<input v-model="input" />
<div class="Wapper" v-if="isShowBlock">
// inputとnameをpropsとして設定
<SimpleArea v-for="(item, i) in componentName" :key="i" :input="input" :name="item" />
</div>
</div>
</template>
<script>
・・・
export default {
・・・
data() {
return {
input: "",
componentName: ["component1", "component2", "component3"],
isShowBlock: true,
};
},
・・・
}
</script>
Vueの場合は双方向データバインディングを採用しているので
<input v-model="input" />
上のようにv-model
キーワードに変数を入れるだけど終わりです。
少し詳細に説明するとタグによって違いますが、
input
のv-model
の場合、
変数を設定する:value
と入力された時にトリガーされる@input
が含めています。
そのため、
<input v-model="input" @input="event => input = event.target.value + 1"/>
上見たいにInputと同時に他の処理を入れたく、@input
を設定しまうと
内部的には@input
処理が二つ存在することになるので、
v-model
を使う時には特に注意する必要があります。
その場合は、v-model
を使わず、:value
と@input
を使うほうが良いでしょう。
詳細な内容に関しては以下のリンクをご覧ください。
なぜVueを使うべきか:文法
ここまででVueとReactの文法について比較して見ました。
結論的にはReactの場合はJavaScriptの文法をそのまま使っているどころが多い面があり、
Vueの場合はVueだけの文法があります。
Vueの一番いいところはv-for
とv-if
と言うものがあり、
IFとFORをタグ内に使えるところです。
この二つだけでも
これだけども全体的なコードが綺麗になるので
Vueを使うメリットは十分あります。
あと、v-model
と言う双方向データバインディングも良い面かと思います。
もちろん注意は必要です。
つまりプロダクト早めに作りたい・ラニングコストが低いほうを大事するプロジェクトであれば
Vueのほうが良いかと思います。
もちろん、JavaScriptに慣れているメンバーが多いとか
柔軟性が必要であればReactになりますね。
あと、全世界的にVueよりはReactのほうを使っているので
Reactの情報が多い面もReactのメリットになります。
次の記事では今までの記事をまとめて結論を出してみましょう。
参考
Discussion