[[📗14 帰ってきたイベントハンドリング]] < [[📒Vue.jsクエスト]] > [[📗16 リポジトリ検索の死闘]]
## Abstract
この先は中ボスですが、その前に[[inputタグ]]のスマートな実装方法を学びましょう。
## Lesson
[[v-model]]ディレクティブを使うと、[[inputタグ]]の実装をよりシンプルに書けます。
たとえば以下のコードは
```html
<script setup lang="ts">
import { ref } from "vue";
const text = ref("");
const handleInput = (e: Event) => {
text.value = (e.target as any).value;
};
</script>
<template>
<div>
<span>{{ text }}</span>
<button @click="text = ''">クリア</button>
</div>
<input :value="text" @input="handleInput" />
</template>
```
以下のようになります。
```html
<script setup lang="ts">
import { ref } from "vue";
const text = ref("");
</script>
<template>
<div>
<span>{{ text }}</span>
<button @click="text = ''">クリア</button>
</div>
<input v-model="text" />
</template>
```
## Missions
### Mission 1
#😁EASY
以下のコードが期待通り動作するよう書き換えてください。
```html
<script setup lang="ts">
import { ref } from "vue";
const checked = ref(false);
</script>
<template>
<div>check: {{ checked }}</div>
<input type="checkbox" :v-model="checked" />
</template>
```
%%
回答例
```html
<script setup lang="ts">
import { ref } from "vue";
const checked = ref(false);
</script>
<template>
<div>check: {{ checked }}</div>
<input type="checkbox" v-model="checked" />
</template>
```
%%
### Mission 2
#🙂NORMAL
以下破線内のようなUIのコードを書いてください。ただし、『選択した文字列がここに表示される』は固定文言ではなく、選択された項目の文字列が表示されるものとします。
<div style="padding: 15px; border: dotted 1px">
<div>選択した文字列がここに表示される</div>
<select>
<option>タツヲ</option>
<option>みみぞう</option>
<option>マサハル</option>
</select>
</div>
%%
回答例
```html
<script setup lang="ts">
import { ref } from "vue";
const selected = ref("タツヲ");
</script>
<template>
<div>{{ selected }}</div>
<select v-model="selected">
<option>タツヲ</option>
<option>みみぞう</option>
<option>マサハル</option>
</select>
</template>
```
%%
### Mission 3
#🙂NORMAL
以下のコードについて、入力欄が変わった時ではなく、入力欄からフォーカスが外れた時に表示を変更するよう、コードを修正してください。
```html
<script setup lang="ts">
import { ref } from "vue";
const text = ref("");
</script>
<template>
<div>{{ text }}</div>
<input type="text" v-model="text" />
</template>
```
%%
回答例
```html
<script setup lang="ts">
import { ref } from "vue";
const text = ref("");
</script>
<template>
<div>{{ text }}</div>
<input type="text" v-model.lazy="text" />
</template>
```
%%
> [!hint]- Hint 1
> https://vuejs.org/guide/essentials/forms.html#lazy
### Mission 4
#😵HARD
以下破線内のようなUIのコードを書いてください。ただし、『選択したキャラの画像が表示される』は固定文言でなく、選択された項目に紐づく画像が表示されるものとします。
<div style="padding: 15px; border: dotted 1px">
<div>選択したキャラの画像が表示される</div>
<select>
<option>タツヲ</option>
<option>みみぞう</option>
<option>マサハル</option>
</select>
</div>
選択肢と画像URLのマッピングは以下。
| 選択肢 | 画像URL |
| -------- | ---------------------------------------------------------------------------------------------------------------------------- |
| タツヲ | https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/Notes/attachments/tatsuwo.jpg |
| みみぞう | https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/Notes/attachments/Pasted%20image%2020210605212644.png |
| マサハル | https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/Notes/attachments/masaharu.jpg |
> [!hint]- Hint 1
> https://vuejs.org/guide/essentials/forms.html#value-bindings
%%
回答例
[[v-for]]を使えれば及第点。
```html
<script setup lang="ts">
import { ref } from "vue";
const values = [
{
name: "タツヲ",
url: "https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/Notes/attachments/tatsuwo.jpg",
},
{
name: "みみぞう",
url: "https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/Notes/attachments/Pasted%20image%2020210605212644.png",
},
{
name: "マサハル",
url: "https://publish-01.obsidian.md/access/35d05cd1bf5cc500e11cc8ba57daaf88/Notes/attachments/masaharu.jpg",
},
];
const selected = ref(values[0]);
</script>
<template>
<img :src="selected.url" style="height: 480px; display: block" />
<select v-model="selected">
<option v-for="v in values" :value="v">{{ v.name }}</option>
</select>
</template>
```
%%
## References
- [Form Input Bindings \| Vue\.js](https://vuejs.org/guide/essentials/forms.html)