本篇文章主要介紹 v-model 在 Vue2 和 Vue3 中使用變化。
一、Vue2 中 v-model 的使用
v-model 是語法糖,本質還是父子元件間的通訊。父子元件通訊時有兩種方式:
- 父給子傳值:通過 props
- 子給父傳值:通過 Events up,使用 $emit 觸發事件。
1.1、父元件給子元件傳值
父元件程式碼
<child :msg="msg" />
<script>
export default{
data(){
return{
msg:"父元件給子元件傳值"
}
}
}
</script>
子元件程式碼
<template>
<div>
{{msg}}
</div>
</template>
<script>
export default{
props:{
msg:{
type:String,
default:""
}
}
}
</script>
props 是單向資料流,子元件只能讀取,並不能修改 msg 。物件型別可以,但不建議修改。
1.2、父子元件雙向繫結
子元件同步一個資料的時候,子元件既要使用,還要修改這個資料,以前需要通過 props Down 和 Events Up 來實現。現為了方便,提供了特殊的語法糖 v-model 。
父元件程式碼:
{{msg}}
<set-input v-model="msg" />
子元件 SetInput.vue 檔案程式碼
<template>
<div>
<input type="text" v-model="newValue">
</div>
</template>
<script>
export default {
props:{
value:{
type:String,
default:''
}
},
computed:{
newValue:{
get:function(){
return this.value
},
set:function(value){
this.$emit('input',value)
}
}
}
}
</script>
v-model = "msg" 可以翻譯為:
:value="msg"
@input="msg=$events"
所以父元件的程式碼可以翻譯為:
<set-input :value="msg" @input="msg=$events" />
在一個元件上,v-model 只能使用一次,如果想要對多個資料同步繫結,則可以使用.sync修飾符。
二、.sync修飾符
.sync 和 v-model 都是語法糖,本質還是父子元件間的通訊。使用 .sync 修飾符實現父子元件多個資料雙向繫結。
因為 vue2 中元件只能定義一個 v-model,如果父子需要實現多個資料雙向繫結,就需要藉助 .sync 修飾符。
.sync 使用原理:
<child-comp v-model="msg" :foo.sync="foo" />
//可翻譯為
<child-comp
:value="msg" @input="msg=$event"
:foo="foo" @update:foo="foo=$event" />
/*********** 一個完整的程式碼示例 *************/
//父元件程式碼
<child-comp v-model="msg" :foo.sync="foo" />
//子元件程式碼
<template>
<div>
<input type="text" v-model="newFoo">
<input type="text" v-model="newValue">
</div>
</template>
<script>
export default {
props:{
value:{
type:String,
default:''
},
foo:{
type:String,
default:""
}
},
computed:{
newValue:{
get:function(){
return this.value
},
set:function(value){
this.$emit('input',value)
}
},
newFoo:{
get:function(){
return this.foo
},
set:function(value){
this.$emit('update:foo',value)
}
}
}
}
</script>
三、Vue3.x 使用 v-model
vue2 中的 v-model 和 .sync 功能重疊,容易混淆,因此 vue3 做了統一,一個元件可以多次使用 v-model 。
3.1、vue 3 的v-model使用原理:
<child-comp v-model="msg" /> //可翻譯為 <child-comp :modelValue="msg" @update:modelValue="msg=$event" />
單個資料雙向繫結完整示例
//父元件程式碼
<child-comp v-model="name" />
子元件程式碼:
<template>
<input type="text" v-model="newValue">
</template>
<script>
export default {
props:{
modelValue:{
type:String,
default:''
}
},
computed:{
newValue:{
get:function(){
return this.modelValue
},
set:function(value){
this.$emit('update:modelValue',value)
}
}
}
}
</script>
vue3 使用特定的 modelValue ,避免 value 的佔用,通過 update:modelValue 實現資料雙向繫結。值得注意的是,vue3 移除了 model 選項。
3.2、多個 v-model 使用
在 vue3 一個元件可以使用多個 v-model ,統一了 vue2 的 v-model 和 .sync 修飾符。
使用原理:
<child-comp v-model:name="name" v-model:age="age" />
//可翻譯為
<child-comp
:name="name" @update:name="name=$event"
:age="age" @update:age="age=$event" />
實現多個資料雙向繫結完整例項:
//父元件程式碼
<child-comp v-model:name="name" v-model:age="age" />
//子元件程式碼
<template>
<div>
<input type="text" v-model="newName">
<input type="text" v-model="newAge">
</div>
</template>
<script>
export default {
props:{
name:{
type:String,
default:''
},
age:{
type:String,
default:""
}
},
emits:['update:name','update:age'],
computed:{
newName:{
get:function(){
return this.name
},
set:function(value){
this.$emit('update:name',value)
}
},
newAge:{
get:function(){
return this.age
},
set:function(value){
this.$emit('update:age',value)
}
}
}
}
</script>
需要注意的是 script 中多了一個 emits 選項,你發現了嗎?
vue3 元件的自定義事件需要定義在 emits 選項中,只要是自定義事件,就需要新增在 emits 中,否則會有警告。它的優點:
- 如果與原生事件相同名時,事件就會被觸發兩次,如果在 emits 選項中加入時,當作自定義事件處理,只會觸發一次。
- 更好地指示元件的工作方式。
- 可以校驗物件形式的事件。
四、總結
從 vue2.0 開始,元件上自定義 v-model 進行資料雙向繫結,不斷改進它的使用。過程如下:
<child-comp v-model="msg" />
4.1、vue2.0 可以翻譯為:
<child-comp :value="msg" @input="msg=$event" />
存在問題:v-model 和 value 有一個強繫結關係,如果子元件中有一個 input 原生標籤,此時就會影響原生標籤的 value 和 input 事件。
4.2、vue2.2版本
引入了 model 元件選項,允許開發者任意指定 v-model 的 props 和 event 。這樣就解決了 vue2.0 中的 v-model 和 value 的強繫結關係。但是還是存在一個問題,就是多個資料雙向繫結時,還是需要藉助 .sync 修飾符。
4.3、vue3.x 版本
Vue3 可以翻譯為:
<child-comp :modelValue="msg" @update:modelValue="msg=$event" />
vue3 統一 使用 v-model 進行多個資料雙向繫結,廢除了 model 元件選項。
本篇文章的分享到這就要結束了,喜歡小編的歡迎點個關注!