# [Vue] Custom Component 使用 v-model
###### tags: `Vue` `前端筆記`
## `v-model` 的基本介紹
在一般的表單 component 中,常用 `v-model` 語法糖綁定同 scope input 及 state 的值,讓開發者省略自行動態綁定 value 及傳接更動 state 的事件。
```javascript=
<template>
<input v-model="searchText">
</template>
<script>
export default {
data () {
return {
searchText: 'Lun'
}
}
}
</script>
```
等價於:
```javascript=
<template>
<input
v-bind:value="searchText"
v-on:input="searchText = $event.target.value"
>
</template>
<script>
export default {
data () {
return {
searchText: 'Lun'
}
},
}
</script>
```
==所以可以得知 `v-model` 是 `:value` + `event` 縮寫的語法糖。==
## `v-model` 也可以下在 component 上,透過 `v-model` 的語法糖幫忙簡化更動 parent component state 的方法
==切記心法:`v-model` 是 `:value` + `event` 的縮寫語法糖。==
```javascript=
// App.vue
<template>
<input-component v-model="name"></input-component>
</template>
<script>
import InputComponent from "./InputComponent.vue";
export default {
name: 'APP',
components: {
InputComponent,
},
data () {
return {
name: 'Lun'
}
}
}
</script>
```
```javascript=
// InputComponent.vue
<template>
<input type="text" :value="name" @input="$emit('input', $event.target.value)">
</template>
<script>
export default {
name: 'InputComponent',
// props 告訴 Vue 要往外找接來的資料,此例子是 v-model
props: ['name']
}
</script>
```
因為 `v-model` 是 `:value` + `event` 的縮寫語法糖,所以在 child component 透過 `props` 讓 Vue 得知有外部資料,再手動綁定 `:value` 及 `event`。`evnet` 則因為 child component 要改 parent component 的 state 要透過發射事件(`$evnet`)。
> 手動綁定事件 + `$emit` = 還是「合法地」透過事件改變 parent component 的 state。
(初始化,`App.vue` 及 `TestInput.vue` state 相同)

(`TestInput.vue` 輸入新值了,好險有 `v-model` 同步更新 parent 及 child 的 state)


## Parent 還需要透過自己的事件接 child component 射來的 `$emit` 嗎?
不用,只要在 child component 寫入手動綁定(`props`, `:value` 及 `$emit`),在 parent component 中叫用 child component 寫入 `v-model="keyName"` 即可。
**`v-model="keyName"` -> child component props 要接的 keyName。**
## Vue 3 的大躍進
在 Vue 3 中使用 v-model to custom component 有新的 defaul keyName,讓程式碼的閱讀性更上一層樓。
```javascript=
// App.vue
<template>
<input-component v-model="testValue"></input-component>
</template>
<script>
export default {
data () {
return {
testValue: 'Lun'
}
}
}
</script>
```
```javascript=
// InputComponent.vue
<template>
<input :value="modelValue" @input="$emit('updata:modelValue', $event.target.value)" />
</template>
<script>
export default {
// props 告訴 Vue 有外部的資料,Vue 會自己找來源
// modelValue -> 預設的 v-model keyName
props: {
modelValue: {
type: String
}
}
}
</script>
```
在 Vue 3 提供了預設的 `modelValue` 供開發者使用預設的 keyName 取得 parent 傳的 v-model 資料。
而更新資料的 `emit`,Vue 3 也有語意更明確的 `update:modelValue` 的方法,讓開發者更明白這個是更新 parent state。
(parent 透過 v-model 與 child 雙向綁定)

(Vue 3 預設的 `modelValue` 以及 `update:modelValue`)

(多虧 v-model 雙向綁定,parent 跟 child 的 state 都有同步更新)


### 除了預設 `modelValue` 及 `update:modelValue` 外,開發者可以自行命名
從上部分可以得知,child 中是透過 props 預設的 `modelValue` 接 parent 的 v-model 綁定資料。
但是開發者也可以自行命名,做法很簡單,就把 parent 給 child 的 `v-model="valueKey"`,改寫成 `v-model:customName="valueKey"` 就好了。(連更新的 `emit` 也要使用 v-model 的名字)
```javascript=
// App.vue
<template>
<input-component v-model:myName="testValue"></input-component>
</template>
<script>
export default {
data () {
return {
testValue: 'Lun'
}
}
}
</script>
```
```javascript=
// InputComponent.vue
<template>
<input :value="myName" @input="$emit('updata:myName', $event.target.value)" />
</template>
<script>
export default {
// props 告訴 Vue 有外部的資料,Vue 會自己找來源
// 因為 parent 有給名字,所以就要使用名字
props: {
myName : {
type: String
}
}
}
</script>
```
(parent 中的 state)

(因為 v-model 有給名字,所以 child 也需要使用名字)-> 在開發者工具也可以看到有名字的 `props` 及 `updata:customName`

(child 跟 parent 都有綁在一起)


## 參考資料
1. [Using v-model on Components](https://v2.vuejs.org/v2/guide/components.html#Using-v-model-on-Components)
2. [How To Add v-model Support to Custom Vue.js Components](https://www.digitalocean.com/community/tutorials/how-to-add-v-model-support-to-custom-vue-js-components)
3. [Vue.js Tip #1: Use V-Model on Custom Components](https://javascript.plainenglish.io/vue-js-tip-1-use-v-model-on-custom-components-be56401727e0)
4. [Vue JS 3 Tutorial - 36 - Components and v-model](https://www.youtube.com/watch?v=CALrQCw41dI)
5. [VueJS. v-model in custom component](https://stackoverflow.com/questions/46258763/vuejs-v-model-in-custom-component)
6. [008 天絕對看不完的 Vue.js 3 指南 - 2.2.7 v-model 與元件的雙向綁定](P.121 - P.122)
7. [Vue - The Complete Guide (incl. Router & Composition API) - lecture: 147](https://www.udemy.com/course/vuejs-2-the-complete-guide/learn/lecture/21526418#questions)