Vue.jsのディレクティブを学ぶ
前回に引き続き、今回はVue.jsのディレクティブを学んだのでまとめていきます。
ディレクティブというのは、Vue.jsにて独自に定義される属性値で、”v-xxxxx”の形式で記載されます。
v-text
script側にて設定・定義した値(テキスト内容)をhtml上に設定します。
<!-- 以下には、"v-textのテスト"の文字列がセットされる -->
<span v-text="textTest"></span>
<script type="module">
const { createApp } = Vue;
createApp({
data(){
return {
textTest: 'v-textのテスト'
}
}
}).mount('#app')
</script>
v-html
v-textのhtml版です。HTMLとして挿入されます。
クロスサイトスクリプティング(XSS)攻撃につながる可能性があるため、このディレクティブにユーザーの入力項目を使用しないよう、公式ドキュメントにて注意喚起されています。
<!-- 以下には、赤字で"HTML文字列のテスト"の文字列がセットされる -->
<span v-html="htmlTest"></span>
<script type="module">
const { createApp } = Vue;
createApp({
data(){
return {
htmlTest: '<span style="color: red">HTML文字列のテスト</span>'
}
}
}).mount('#app')
</script>
v-show
bool値を設定し、trueであれば対象の画面要素は表示、falseであれば非表示となります。
<span v-show="isSoldOut">現在売り切れ中</span>
v-if, v-else, v-else-if
条件に沿って画面要素のレンダリングを制御します。
<!-- ※stockは0以上である前提とする -->
<span v-if="stock===0">在庫なし</span>
<span v-else-if="stock<10">在庫わずか</span>
<span v-else>在庫あり</span>
※v-showでfalseの場合は display: none による非表示となり、v-if, v-else, v-else-ifでfalseの場合は画面要素自体がレンダリングされないという違いがあります。
v-for
元のデータ分だけループして画面要素を複数レンダリングします。
<!-- 元データのbloodTypesの要素数分だけ(4回)レンダリングされる -->
<div v-for="bloodType in bloodTypes">
{{bloodType.id}} : {{bloodType.name}}
</div>
<script type="module">
const { createApp } = Vue;
createApp({
data(){
return {
bloodTypes: [
{
"id":"A",
"name":"A型"
},
{
"id":"B",
"name":"B型"
},
{
"id":"O",
"name":"O型"
},
{
"id":"AB",
"name":"AB型"
}
]
}
}
}).mount('#app')
</script>
v-on
画面要素にイベントリスナーを追加します。onclickとかのonのイメージです。
“v-on:”の代わりに”@”と省略して記載することもできます。
<div>
<button v-on:click="showAlert('v-onによる記述')">v-onによるメソッド実行</button>
</div>
<div>
<button @click="showAlert('@による記述')">@によるメソッド実行</button>
</div>
<script type="module">
const { createApp } = Vue;
createApp({
methods:{
showAlert(message){
alert(message)
}
}
}).mount('#app')
</script>
v-bind
画面要素の属性をバインドします。
<div>
<!-- input要素のvalue属性に、inputDefaultTextの値をセット -->
<input v-bind:value="inputDefaultText">
</div>
<div>
<!-- style属性のcolorの値に、colorRedの値をセット -->
<span :style="{ color: colorRed }">※"v-bind:"を":"と省略することも可能</span>
</div>
<script type="module">
const { createApp } = Vue;
createApp({
data(){
return {
inputDefaultText: "デフォルト",
colorRed: "#ff0000"
}
}
}).mount('#app')
</script>
その他
ここに挙げた以外にも、以下のようなものがあります。
自分用のメモレベルで記載しておきます。
- v-model
→input, textarea, select要素において、画面上の値と、JavaScript上の変数値の状態とを同期する。 - v-slot
→親コンポーネント側から、子コンポーネント内に値を挿入する。
参考:Vue.jsのslotの機能を初心者にわかるように解説してみた | フューチャー技術ブログ - v-pre
→要素内でVueテンプレートの構文が使用されていてもそのままレンダリングされ、表示される。 - v-once
→一度だけレンダリングされる。 - v-memo
→指定した値すべてが最後のレンダリング結果を同じ場合、レンダリングをスキップする。
参考:【Vue3】v-memoディレクティブでレンダリングを最適化する - v-cloak
→付与された画面要素は、コンパイル完了するまで残る。[v-cloak]{display:none}と組み合わせることで、コンパイル完了まで画面要素を表示させないようなことができる。
テスト用コード
勉強用に作ったコードを一応載せておきます。
(前回同様、CDN版を使用しています)
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>my vue directive study</title>
</head>
<body>
<div id="app">
<h1>Vue.js ディレクティブの動作確認</h1>
<hr/>
<h2>v-text</h2>
<span v-text="textTest"></span>
<hr/>
<h2>v-html</h2>
<span v-html="htmlTest"></span>
<hr/>
<h2>v-show</h2>
<span v-show="boolTrue">こちらは見える</span>
<span v-show="boolFalse">こちらは見えない</span>
<hr/>
<h2>v-if, v-else, v-else-if</h2>
<span v-if="stock===0">在庫なし</span>
<span v-else-if="stock<10">在庫わずか</span>
<span v-else>在庫あり</span>
<hr/>
<h2>v-for</h2>
<div v-for="bloodType in bloodTypes">
{{bloodType.id}} : {{bloodType.name}}
</div>
<hr/>
<h2>v-on</h2>
<div>
<button v-on:click="showAlert('v-onによる記述')">v-onによるメソッド実行</button>
</div>
<div>
<button @click="showAlert('@による記述')">@によるメソッド実行</button>
</div>
<hr/>
<h2>v-bind</h2>
<div>
<input v-bind:value="inputDefaultText">
</div>
<div>
<span :style="{ color: colorRed }">※"v-bind:"を":"と省略することも可能</span>
</div>
<hr/>
<h2>v-model</h2>
<input v-model="searchText" />
<!-- 上記のv-modelは以下と同義
<input
:value="searchText"
@input="searchText = $event.target.value"
/>
-->
<hr/>
<h2>v-pre</h2>
<span v-pre>{{textTest}} ← v-preが付与されるとそのまま表示される</span>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@3.2.47/dist/vue.global.min.js"></script>
<script type="module">
const { createApp } = Vue;
createApp({
data(){
return {
textTest: 'v-textのテスト',
htmlTest: '<span style="color: red">HTML文字列のテスト(XSSに注意!ユーザー入力値は設定しないようにすること!)</span>',
boolTrue: true,
boolFalse: false,
stock:0,
bloodTypes: [
{
"id":"A",
"name":"A型"
},
{
"id":"B",
"name":"B型"
},
{
"id":"O",
"name":"O型"
},
{
"id":"AB",
"name":"AB型"
}
],
inputDefaultText: "デフォルト",
colorRed: "#ff0000"
}
},
methods:{
showAlert(message){
alert(message)
}
}
}).mount('#app')
</script>
</body>
</html>
参考URL
ビルトインのディレクティブ | Vue.js
Vue.js入門 マスタッシュ構文、ディレクティブ、オプション – Qiita