<input v-model="str" />
// 等同于
<input :value="str" @input="str = $event.target.value" />
通過上面的代碼脑融,我們可以分析得出转锈,也就是說:<font color=red> v-model="str" 是 :value="str" @input="str = $event.target.value" 的縮寫焚虱。</font>
解釋:
$event 指代當前觸發(fā)的事件對象。
$event.target 指代當前觸發(fā)的事件對象的dom
$event.target.value 就是當前dom的value值
在@input方法中镀岛,value => str
在:value中:str => value
如此,形成了一個閉環(huán)兼都,也就是所說的數(shù)據(jù)的雙向綁定。
自定義組件怎么實現(xiàn)v-model
<my-component v-model="price"></my-component>
我們可以根據(jù)規(guī)則來拆解
<my-component :value="price" @input="price = $event.target.value"></my-component>
那么我們在還原組件的封裝
<template>
<div>
<input type="text" :value="value" @input="$emit('input', $event.target.value)">
</div>
</template>
<script>
export default {
props: {
value: String
}
}
</script>
看到上面的代碼或許你就恍然大悟了稽寒,他又回到了扮碧,我們之前學過的 父子組件的來回傳值。
細心的同學可能會發(fā)現(xiàn)杏糙,我們 props 里面的值是 value 那我能不能隨便定義一個變量呢慎王?還有 $emit()里面?zhèn)魅氲氖录凳莍nput我能不能也隨便定義一個事件呢?
當我們在一個自定義組件上使用v-model并不能實現(xiàn)雙向綁定宏侍,因為自定的組件并沒有默認的value和input事件赖淤,在使用時,我們需要按照上面那樣顯式的去聲明定義這些東西谅河。這時咱旱,model選項就派上用場了,在定義組件的時候旧蛾,指定prop的值和監(jiān)聽的事件莽龟。
組件的用法是不變的,子組件可以這么寫
<template>
<div>
<input type="text" :value="xxxx" @input="$emit('xxxx', $event.target.value)">
</div>
</template>
<script>
export default {
model:{
prop:'xxxx',
event:'xxxx' // 代表自定義的事件名稱
}
props: {
xxxx: String // 代表自定義的變量名稱
}
}
</script>
這就是vue 的 model 選項的作用锨天。
以上是vue2.0的v-model語法糖講解,vue3.0是怎么用的呢剃毒?
其實vue3的v-model跟vue2的使用區(qū)別不大病袄,只是跟vue2的 <font color=red>sync</font> 修飾符進行了合并,所以在vue3中就移除了 <font color=red>sync</font> 修飾符赘阀。下面我們看看怎么在 <font color=red>composition api</font>
中怎么寫 <font color=red>v-model</font>
// 自定義一個TestModel組件
<template>
<div>
<input type="text" :value="modelValue" @input="$emit('update:modelValue', $event.target.value)" />
</div>
</template>
<script>
export default {
props: {
modelValue: {
type: String
}
}
}
</script>
在vue3中默認的不在是value 而是modelValue
然后在其他頁面使用
<template>
<h1>vue3中使用v-model {{msg}}</h1>
<testModel v-model="msg"></testModel>
<!-- 等同于下面語法 默認傳入一個modelValue 然后子組件接收這個modelValue -->
<testModel :modelValue="msg" @update:modelValue="msg = $event"></testModel>
</template>
<script>
import { ref } from 'vue';
import testModel from './TestModel.vue';
export default {
components: {
testModel
},
setup(){
const msg = ref('')
return { msg }
},
}
</script>
有的小伙伴可能有疑問益缠,如果我不想用 modelValue 怎么辦呢?當然也可以寫成其他的名字
// 父組件
<template>
<h1>vue3中使用v-model {{msg}}</h1>
<testModel v-model:msg="msg"></testModel>
</template>
子組件接收的props就要改成msg了
// 子組件
<template>
<div>
<input type="text" :value="msg" @input="$emit('update:msg', $event.target.value)" />
</div>
</template>
<script>
export default {
props: {
msg: {
type: String
}
}
}
</script>
當然提到雙向綁定基公,你可能第一時間就會想到表單元素幅慌,雙向綁定不一定是表單元素,你可以定義各種各樣的組件轰豆,比如通過click事件改變父組件的值
// 父組件
<template>
<div>{{count}}</div>
<testModel v-model:count="count"></testModel>
</template>
<script>
export default {
components: {
testModel
},
setup(){
const count = ref(0)
return { count }
}
}
</script>
// 子組件
<template>
<!-- 一定是+1 不是+=1 或者++ 否則vue會觸發(fā)一個不讓子組件直接改變props的警告 -->
<div @click="$emit('update:count', count + 1)">click me count + 1胰伍!</div>
</template>
<script>
export default {
props: {
count: {
type: Number
}
}
}
</script>