極速上手 VUE 3—v-model 的使用變化

前端人發表於2021-11-02

本篇文章主要介紹 v-model 在 Vue2 和 Vue3 中使用變化。

一、Vue2 中 v-model 的使用

v-model 是語法糖,本質還是父子元件間的通訊。父子元件通訊時有兩種方式:

  1. 父給子傳值:通過 props
  2. 子給父傳值:通過 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 中,否則會有警告。它的優點:

  1. 如果與原生事件相同名時,事件就會被觸發兩次,如果在 emits 選項中加入時,當作自定義事件處理,只會觸發一次。
  2. 更好地指示元件的工作方式。
  3. 可以校驗物件形式的事件。

四、總結

從 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 元件選項。


本篇文章的分享到這就要結束了,喜歡小編的歡迎點個關注!

相關文章