［Vue3］データバインドざっくりまとめ

#　概要
v-bindやv-htmlは片方向データバインディングで、v-modelは双方向データバインディング。


# イメージ
## 片方向データバインディング
・テンプレートに値をバインドする場合
![スクリーンショット 2023-09-27 145733.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513331/6ece99cd-7b2a-3303-bed2-e12add96f820.png)

・入力から変数にバインドする場合
![スクリーンショット 2023-09-27 145903.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513331/b5187152-1641-60aa-afcc-8b689d5e1ad5.png)



## 双方向データバインディング
![スクリーンショット 2023-09-27 145819.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/513331/3be87419-6309-3969-5489-89d59c59d25d.png)

# v-model
inputから入力した内容が即時に反映される。
input:textに限らずradio、checkbox、selectでも同様にデータバインドが行える。

```:記法
v-model=”変数名”
```

```App.vue
<script setup lang="ts">
import { ref } from "vue";
const inputNameModel = ref("バインド");
</script>

<template>
	<section>
		<input type="text" v-model="inputNameModel">
		<p>{{ inputNameModel }}</p>
	</section>
</template>

```

```html:レンダリング結果
<section>
	<input type="text">
		<p>バインド</p>
</section>
```

```:出力結果
［あああ］　// input:text
あああ
```

## v-modelの修飾子
<table>
	<tr>
		<td>修飾子</td>
		<td>内容</td>
	</tr>
	<tr>
		<td>lazy</td>
		<td>inputの代わりにchangeイベントでバインドを行う<br>（対象のフォームからフォーカスが外れてからバインド）</td>
	</tr>
	<tr>
		<td>number</td>
		<td>入力値を数値として扱う</td>
	</tr>
	<tr>
		<td>trim</td>
		<td>入力値の前後の空白を取り除く</td>
	</tr>
</table>

# v-bind
scriptタグ内で変数を指定し、v-bindで属性値をバインドする。
scriptタグ内からtemplateタグ内に値を渡すイメージ。

v-bindではHTMLタグの同様に属性値をダブルクォーテーションで囲む必要がある。
そのため、その中にさらに文字列を記述する場合は、シングルクォーテーションを利用することになる。
また、オブジェクト内で指定されているalt属性がテンプレート側に記述されている場合、後にある記述が優先される。（次項でサンプル）

```:記法
v-bind:属性名=”変数名(もしくは値)”

・v-bindの省略も可能
:属性名=”変数名(もしくは値)”
```

```App.vue
<script setup lang="ts">
import {ref} from "vue";

const url = ref("https://vuejs.org/");
</script>

<template>
	<p><a v-bind:href="url" target="_blank">Vue.jsのサイト</a></p>
	<p><a :href="url" target="_blank">Vue.jsのサイト(省略系)</a></p>
	<p><a v-bind:href="url + 'guide/introduction.html'" target="_blank">Vue.jsガイドのページ</a></p>
</template>

```

```html:レンダリング結果
<p><a href=" https://vuejs.org/" target="_blank"> Vue.jsのサイト</a></p>
<p><a href=" https://vuejs.org/" target="_blank"> Vue.jsのサイト(省略系)</a></p>
<p><a href=" https://vuejs.org/guide/introduction.html" target="_blank"> Vue.jsガイドのページ</a></p>
```

## 複数の属性をまとめてバインド
オブジェクトとして宣言する。

```App.vue
<script setup lang="ts">
import {ref} from "vue";

const imgAttr = ref({
	src: "/images/logo.svg",
	alt: "ロゴ",
	width: 75,
	height: 75
});
</script>

<template>
	<div><img v-bind="imgAttr"></div>
    <div><img v-bind="imgAttr" alt="logo"></div>
    <div><img alt="logo" v-bind="imgAttr"></div>
</template>

```

```html:レンダリング結果
<img src="/images/logo.svg" alt="Vueのロゴ" width="75" height="75">
<img src="/images/logo.svg" alt="logo" width="75" height="75">
<img src="/images/logo.svg" alt="Vueのロゴ" width="75" height="75">
```

## v-bind属性の一例
### v-bind:style
スタイルをバインドする。
```App.vue
<script setup lang="ts">
import {ref} from "vue";

const msg = ref("こんにちは");
const myStyles = ref({
	color: "bule",
	fontSize: "24pt"
});
</script>

<template>
	<p v-bind:style="{ color: 'blue' }">{{ msg }}</p>
	<p v-bind:style="myStyles">{{ msg }}</p>
</template>
```

```html:レンダリング結果
<p style="color: bule;">こんにちは</p>
<p style="color: bule; font-size: 24pt;">こんにちは</p>
```

### v-v-bind:class
htmlのclassをバインドする。
```App.vue
<script setup lang="ts">
import {ref} from "vue";

const msg = ref("こんにちは");
const myClass = ref({
	clrBlue: false,
	clrRed: true,
});
</script>

<template>
	<p v-bind:class="{ clrBlue: true }">{{ msg }}</p>
	<p v-bind:class="myClass">{{ msg }}</p>
</template>
```
```html:レンダリング結果
<p class="clrBure">こんにちは</p>
<p class="clrRed">こんにちは</p>
```

### v-v-bind:value
inputのvalue属性をバインドする。
```App.vue
<template>
	<input type="text" name="" id="" v-bind:value="hoge">
</template>
```
```html:レンダリング結果
<input type="text" name="" id="" value="hoge">
```

### v-v-bind:disabled
hidden属性をバインドする。
```App.vue
<template>
	<input type="text" name="" id="" v-bind:disabled="true">
</template>

```
```html:レンダリング結果
<input type="text" name="" id="" disabled>
```


```:主力結果
Vue.jsのサイト　（リンク：https://vuejs.org/）
Vue.jsのサイト(省略系)　（リンク：https://vuejs.org/）
Vue.jsガイドのページ　（リンク：https://vuejs.org/guide/introduction.html）
```

# v-html
v-htmlはHTML文字列をそのまま表示するディレクティブです。

```:記法
v-model=”変数名”
```

```App.vue
<script setup lang="ts">
import { ref } from "vue";

const htmlStr = ref(`<a href="https://vuejs.org//">Vue.jsのTOPページ<a/>`);
</script>

<template>
	<section>{{ htmlStr }}</section>
	<section v-html="htmlStr"></section>
</template>

```

```html:レンダリング結果
<section>
    <a href="https://vuejs.org//">Vue.jsのTOPページ<a/>
</section>
<section>
    <link rel="stylesheet" href="chrome-://fancfknaplihpclbhbpclnmmjcjanbaf/build/content.css">
</section>
```


# その他のディレクティブ
## v-pre
v-preはマスタッシュ構文も含めて配下のタグ内のテンプレート記述を全て無効化し、そのまま表示するディレクティブです。

```App.vue
<template>
	<section v-pre>
		<p v-on:click="showHello">{{hello!}}</p>
	</section>
</template>
```
```:出力結果
{{hello!}}
```
## v-onece
v-onceは最初の1回だけデータバインドを行うディレクティブです。

```App.vue
<script setup lang="ts">
import { ref } from "vue";

const price = ref(1000);
</script>

<template>
	<section>
		<input type="number" v-model="price">円<br>
		<p v-once>金額は{{ price }}円です。</p>
	</section>
</template>
```

```:出力結果
［1000］円
金額は1000円です。　// 値を変更しても表示は変わらない
```

## v-cloak
テンプレートブロックに記述されたマスタッシュ構文は、HTMLが読み込まれた後、ブラウザで動作するJavaScriptによって値が埋め込まれます。
そのため場合によっては値が埋め込まれるまでの一瞬の間にマスタッシュ構文がそのまま表示されてしまうことがあり、これを防ぎたい場合には、該当のタグにv-cloakディレクティブを記述します。
こちらの結果は省略します。

```App.vue
<script setup lang="ts">
import { ref } from "vue";

const hello = ref("こんにちは!");
</script>

<template>
	<p v-cloak>{{ hello }}</p>
</template>

<style>
[v-cloak] {
	display: none;
}
</style>
```