vue2与vue3 v-model的区别

目录

[Vue 2中的v-model](#Vue 2中的v-model)

默认使用

自定义使用

修饰符.sync (Vue2)

[Vue3.x 使用 v-model](#Vue3.x 使用 v-model)

[vue 3 的v-model使用原理](#vue 3 的v-model使用原理)

[多个 v-model 使用](#多个 v-model 使用)

总结


Vue 2中的v-model

在Vue 2中,v-model是一个用于在子组件和父组件之间双向绑定数据的指令。当在子组件中使用v-model时,它默认绑定到value属性,并且在子组件中可以通过$emit('input', newValue)来改变父组件的数据。这种双向绑定非常方便,但有时也可能引起状态管理上的混乱。

v-model 是语法糖,本质还是父子组件间的通信。父子组件通信时有两种方式:

  1. 父给子传值:通过 props
  2. 子给父传值:通过 Events up,使用 $emit 触发事件。

默认使用

vue中,v-model 的值相当于默认传递了一个名为 value 的 prop 和一个名为 input 的方法(注意,这个valueprop是需要在自定义组件内声明的),如下:

父组件

<template>
  <custom-input v-model="message"></custom-input>
</template>

<script>
import CustomInput from './CustomInput.vue';

export default {
  components: {
    CustomInput,
  },
  data() {
    return {
      message: '',
    };
  },
};
</script>

子组件

CustomInput组件内部,你需要接收value属性并在适当的时候触发input事件,以保持与父组件的数据同步。这是CustomInput组件的例子:

<template>
  <input :value="value" @input="$emit('input', $event)">
</template>

<script>
export default {
  props: ['value'],
};
</script>

这样,当在父组件中使用v-model="message"时,CustomInput组件将能够正确地与message数据进行双向绑定。

至于原理,v-model实际上是语法糖,它通过绑定value属性和监听input事件来实现双向数据绑定。当子组件的输入发生变化时,触发input事件,父组件监听到这个事件后更新相应的数据,从而实现数据的双向同步。

自定义使用

默认使用时,事件名inputprop名value是固定的,如果需要修改,就需要在子组件使用 model 选项。如下:

父组件

使用model选项修改属性和事件名实现自➕1 等价于 :num + @change

<!-- 父组件 -->
<template>
	<MyInput v-model="count" />
  <!-- 等价于 -->
  <MyInput :num="count" @change="count=$event" />
</template>

<script>
import MyInput from './components/MyInput.vue'
export default {
  components: { MyInput },
  data() {
    return {
      count: 1
    }
  }
}
</script>

子组件

利用model 选项 修改 props 跟event 完成自定义

<!-- 子组件 -->
<template>
	<div>
    <span>{{num}}</span>
  	<button @click="add">+1</button>
  </div>
</template>

<script>
export default {
  name: 'MyInput',
  model: {
    prop: 'num',    // 将默认value属性改为num
    event: 'change' // 将默认input事件改为change
  }
  props: {
    num: {
      type: Number,
      default: 0
    }
  },
  methods: {
    add() {
      this.$emit('change', this.num+1)
    }
  }
}
</script>

修饰符.sync (Vue2)

.sync的作用

实现父子组件数据之间的双向绑定, 与v-model 类似.

区别:Vue2中一个组件上只能有一个v-model, 而 .sync 修饰符可以有很多个.

.sync修饰符的原理

// 正常父传子: 
<com1 :a="num" :b="num2"></com1>
 
// 加上sync之后父传子: 
<com1 :a.sync="num" .b.sync="num2"></com1> 
 
// 它等价于
<com1 
  :a="num" @update:a="val=>num=val"
  :b="num2" @update:b="val=>num2=val"></com1> 
 
// 相当于多了一个事件监听,事件名是update:a,回调函数中,会把接收到的值赋值给属性绑定的数据项中。

.sync 与 v-model 区别是

相同点: 都是语法糖, 都是可以实现父子组件中的数据的双向通信

区别点:

  • 格式不同: v-model="num" , :num.sync="num"
  • v-model : @input + value
  • :num.sync: @update:num
  • v-model只能用一次; .sync 可以有多个

Vue3.x 使用 v-model

在Vue 3中,v-model引入了一些重要的改进,使其更具可定制性和可扩展性。以下是其中一些重要的改进:

vue 3 的v-model使用原理

v-model 默认绑定的属性名为:modelValue

v-model 默认绑定的事件名为:update:modelValue

// 所以我们需要使用 modelValue 和 update:modelValue 来接收
export default {
	props: ['modelValue'],
	emits: ['update:modelValue']
}

我们可以自定义 v-model 绑定的名称

父组件

// 父组件
<template>
	<son-component v-model:msg='msg'></son-component> // 使用 v-model:name 来自定义名称
</template>

子组件

// 子组件
export default {
	props: ['msg'],
	emits: ['update:msg']
}

单个数据双向绑定完整示例

//父组件代码
<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 中接收 v-model 的方法, Vue2 需要使用 model 来接收

vue3 使用特定的 modelValue ,避免 value 的占用,通过 update:modelValue 实现数据双向绑定。值得注意的是,vue3 移除了 model 选项。

多个 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>  

总结

从 vue2.0 开始,组件上自定义 v-model 进行数据双向绑定,不断改进它的使用。过程如下

<child-comp v-model="msg" /> 

vue2.0 可以翻译为:

<child-comp :value="msg" @input="msg=$event" />

存在问题:v-model 和 value 有一个强绑定关系,如果子组件中有一个 input 原生标签,此时就会影响原生标签的 value 和 input 事件

vue2.2版本

引入了 model 组件选项,允许开发者任意指定 v-model 的 props 和 event 。这样就解决了 vue2.0 中的 v-model 和 value 的强绑定关系。但是还是存在一个问题,就是多个数据双向绑定时,还是需要借助 .sync 修饰符。

vue3.x 版本

Vue3 可以翻译为:

<child-comp :modelValue="msg" @update:modelValue="msg=$event" /> 

vue3 统一 使用 v-model 进行多个数据双向绑定,废除了 model 组件选项。

相关推荐
逐·風3 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
Devil枫3 小时前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试
尚梦4 小时前
uni-app 封装刘海状态栏(适用小程序, h5, 头条小程序)
前端·小程序·uni-app
GIS程序媛—椰子4 小时前
【Vue 全家桶】6、vue-router 路由(更新中)
前端·vue.js
前端青山5 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
毕业设计制作和分享5 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
程序媛小果5 小时前
基于java+SpringBoot+Vue的旅游管理系统设计与实现
java·vue.js·spring boot
从兄6 小时前
vue 使用docx-preview 预览替换文档内的特定变量
javascript·vue.js·ecmascript
凉辰7 小时前
设计模式 策略模式 场景Vue (技术提升)
vue.js·设计模式·策略模式
清灵xmf7 小时前
在 Vue 中实现与优化轮询技术
前端·javascript·vue·轮询