Vue中从v-model,model,.sync到双向数据传递,再到双向数据绑定

本文深入探讨了Vue.js中v-model与.sync指令的工作原理及差异,解析了它们如何实现双向数据绑定与传递,以及在自定义组件中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前面的话

虽然v-model和.sync之间的区别,是非常明显的,但是通过这个去研究下去,就有点意思了。首先说明v-model是.sync的一种特殊情况,也就是当prop是value,vm.$emit('update:input'),这个时候就是传统意义上的v-model,也就是说v-model是model为prop等于value,event为input的特殊情况。

概念

双向数据传递

为了和绑定区分我把他称为传递,也就是父子组件之间的传递

双向数据绑定

和双向数据绑定不同,双向数据绑定则是数据驱动dom,dom反作用于数据,vue通过Object.defineProperty(),实现了数据驱动dom,而通过dom驱动数据很容易实现了,举个例子当<input>,发生变化的时候把变化后的值赋给一个当前页面的局部变量,周而复始的实现双向的数据绑定

v-modle

引用官网上的一句话:通过使用自定义事件可以在自定义的组件中创建v-modle(注意Input中I大写,是因为这个是自定义的一个包装input标签的组件)

<Input v-model="searchText">

等价于,也就是说当使用v-model的时候默认会调用父级组件中的一个用input触发的事件,这个事件就是为了给当前的prop进行重新赋值。

<Input
  v-bind:value="searchText"
  v-on:input="searchText = $event.target.value"
>

如果想顺利的使用v-model还需要对组件进行以下的处理

Vue.component('Input', {
  props: ['value'],
  template: `
    <input
      v-bind:value="value"
      v-on:input="$emit('input', $event.target.value)"
    >
  `
})

详情

双向数据传递

概念:父子组件之间可以相互修改数据

应用:弹窗、表单

实现:v-model,.sync,model

我们先从概念入手,什么是相互修改,我们都知道的是,父子沟通用的是props,子父沟通用的是$emit,那双向传递就显而易见了,就是在父组件使用props传值给子组件,子组件再通过$emit可以调整父组件。

三种实现的差异

v-modle是最特殊的一个,他其实是model和.sync的特殊情况,有代码为证

model

<style>
  input.i911-model-input {
    color: #f747ff;
    border-radius: 4px;
    border: 3px solid #fa4dde;
  }
</style>

<template>
  <div>
    <input
      class="i911-model-input"
      :value="modelInput"
      @click="handleInput"
    />
  </div>
</template>

<script>
  export default {
    name: "ModelInput",
    model:{
      prop:'modelInput',//为了和v-model默认的value区分,将prop改为自定义的名称
      event:'click'//为了和v-model默认的input区分,将event改为click
    },
    props: {
      modelInput: {
        type: String,
        default: 'modelInput'
      }
    },
    methods:{
      handleInput(event){
        this.$emit('click',event.target.value)//自定义组件中使用v-model都需要通过$emit触发
      }
    }
  }
</script>

sync

<style>
  input.i911-sync{
    color: #801a27;
    border-radius: 4px;
    border: 3px solid #ff375a;
  }
</style>
<template>
  <main>
    <input class="i911-sync"
           :value="msg"
           @input="handleInput"
    >
  </main>
</template>

<script>
  export default {
    name: "SyncInput",
    props: {
      msg: {
        type: String,
        default: ''
      }
    },
    methods:{
      handleInput(event){
        this.$emit('update:msg',event.target.value)
      }
    }
  }
</script>

v-model

<style>
  input.i911-v-model{
    color:green;
    border-radius: 4px;
    border: 3px solid #36ff7a;
  }
</style>
<template>
  <main>
    <input class="i911-v-model"
      :value="value"
      @input="handleInput"
    >
  </main>
</template>

<script>
  export default {
    name: "VModel",
    props: {
      value: {
        type: String,
        default: ''
      }
    },
    methods:{
      handleInput(event){
        this.$emit('input',event.target.value)//这里$emit调用的是默认的input
      }
    }
  }
</script>

子组件贴完了该我们的父组件了

<style>
input.temp-normal-input{
  color: #1ab0ff;
  border: 3px solid #faf847;
}
  input{
    float: left;
  }
</style>

<template>
  <div>
    TEMP
    //直接通过v-model绑定,通过input触发
    V-MODEL-INPUT:<VMolde v-model="value"></VMolde>
    //这里使用了默认input标签的v-model,因此不需要绑定@input='handleInput',便可以对value修改
    V-MODEL-INPUT-PARENT:<input v-model="value">

    //通过:msg.sync绑定,它实质上是@update:msg='val=>valueSync=val',的语法糖,因此可不用绑定
    SYNC-INPUT:<SyncInput :msg.sync="valueSync"></SyncInput>
    SYNC-INPUT-PARENT:<input v-model="valueSync"><br>

    //直接通过v-model绑定,通过input触发
    NORMAL-INPUT-1:<input class="temp-normal-input" v-model="normalValue"/><br>
    NORMAL-INPUT-2:<input v-model="normalValue"/><br>

    MODEL-INPUT:<model-input v-model="modelValue"></model-input>
    MODEL-INPUT-parent:<input v-model="modelValue"/>
  </div>
</template>

<script>
  import VMolde from '@/components/VMolde'
  import SyncInput from '@/components/SyncInput'
  import ModelInput from '@/components/ModelInput'

  export default {
    name: "temp",
    data() {
      return {
        value:'value',
        valueSync:'valueSync',
        normalValue:'normalValue',
        modelValue:'modelValue'
      }
    },
    methods: {
      handleSyncInput(event){
        this.valueSync=event.target.value;
      }
    },
    components: {
      VMolde,
      SyncInput,
      ModelInput
    }
  }
</script>

对比

model&.sync

双向数据绑定

后续总结,可以先看双向数据绑定原理

双向数据传递与双向数据绑定的区别详解

有个问题可能会比较疑惑,v-model不是用来双向数据绑定的吗,为什么也可以用来做双向数据传递,这是什么鬼。但是如果把默认的标签也想成一个组件的话这个问题就迎刃而解了,当使用input标签时,input的内部也有一段类似于上文中自定义Input的代码。

现在我们具体分析,首先我们来分析下在父组件中修改一个被v-model绑定的input标签(也就是子组件)时候发生了什么?

1.双向数据传递(子组件传递给父组件)

核心部分也就是通过$emit调用父组件的input方法去改变输入的value,这一步是干嘛呢?其实就是将子组件的value通过$emit传递给了父级组件,这部分属于数据传递中子组件传递给父组件;

2.双向数据绑定(dom修改value)

而调用的input方法中的对value进行的修改,这个时候就是双向数据绑定中的dom去修改value

反之如果通过父组件直接修改数据使得子组件发生变化这经历了下面的过程

 

3.双向数据传递(父组件传递给子组件)

当父组件的数据发生变化后,父组件通过prop将数据传递给了子组件

4.双向数据绑定(value修改value)

子组件数据变化后要去动态的修改dom,这个时候就是用到了Object.defineProperty()中的set,监听其数据变化,并且修改dom,vue具体dom修改方式还没有看,不过可以理解为通过jquery或者原生js进行修改

 

 

 

 

 

 

 

 

 

 

 

<think>好的,我现在需要回答用户关于Vue3中v-model.sync修饰符的区别、使用场景及实现原理的问题。首先,我需要回忆Vue3的相关知识,并参考用户提供的引用内容。用户提供的引用主要是关于Vue2中的v-model.sync,但用户现在问的是Vue3的情况,所以我需要对比两者的变化。 首先,Vue3中对v-model做了较大的调整。我记得在Vue2中,一个组件只能使用一个v-model,而.sync修饰符用于多个prop的双向绑定。但在Vue3中,v-model可以支持多个,并且.sync修饰符已经被移除了,改为通过v-model的参数来实现类似的功能。 然后,实现原理方面,Vue2的v-model默认使用value属性和input事件,而.sync使用update:propName的事件。在Vue3中,v-model默认使用modelValue属性和update:modelValue事件,同时可以带参数,比如v-model:title,这样就对应title属性和update:title事件,这实际上替代了Vue2中的.sync功能。 使用场景方面,Vue3中v-model更加灵活,可以用于多个数据流的双向绑定,而不再需要.sync修饰符。因此,在Vue3中,推荐统一使用v-model来处理各种情况,无论是单个还是多个prop的双向绑定。 需要注意的是,用户提供的引用中提到的Vue2的.sync和v-model的区别,比如.sync可以多个而v-model只能一个,这在Vue3中已经改变了。因此,在回答时要明确指出Vue3的变化,避免混淆。 接下来,我需要整理这些点,并按照用户的要求结构清晰、分点说明,同时引用提供的参考资料。用户提供的引用中有关于Vue2的区别,比如引用3和5提到.sync和v-model的功能区别,但需要转换为Vue3的情况。 可能还需要检查Vue3的官方文档或可靠来源,确认我的记忆是否正确,比如v-modelVue3中的默认属性和事件名称,以及.sync是否真的被废弃。根据Vue3的文档,确实.sync已被废弃,改用带参数的v-model。 最后,生成相关问题,确保问题与主题相关,帮助用户深入理解。</think>### Vue3中v-model.sync修饰符的区别及使用场景 #### 1. **实现原理对比** - **v-model** 在Vue3中,`v-model`默认绑定的是`modelValue`属性和`update:modelValue`事件,且支持多个双向绑定参数。例如: ```html <ChildComponent v-model:title="pageTitle" v-model:content="pageContent" /> ``` 子组件通过`props.title`接收数据,并通过`emit('update:title', newValue)`更新父组件数据[^5][^4]。 - **.sync修饰符** **Vue3已移除.sync修饰符**,其功能被`v-model`参数化替代。Vue2中`.sync`通过`update:propName`事件实现双向绑定,例如: ```html <!-- Vue2语法(Vue3已废弃) --> <ChildComponent :title.sync="pageTitle" /> ``` 子组件需触发`this.$emit('update:title', newValue)`[^3]。 #### 2. **核心区别** | 特性 | Vue3的v-model | Vue2的.syncVue3已废弃) | |---------------------|----------------------------------|--------------------------------| | **绑定数量** | 支持多个(如`v-model:prop1`) | 支持多个 | | **默认属性/事件名** | `modelValue`与`update:modelValue` | 无默认,需手动指定`propName` | | **语法简洁性** | 统一使用`v-model`,无需修饰符 | 需`.sync`修饰符 | #### 3. **使用场景** - **v-model** 适用于需要明确语义的**表单组件**(如输入框、下拉框)或**单一核心数据**绑定。例如: ```html <CustomInput v-model="username" /> ``` 子组件通过`props.modelValue`接收数据,并通过`emit('update:modelValue')`更新[^5][^1]。 - **多参数v-model** 替代Vue2的`.sync`,用于**多个独立数据流**的双向绑定。例如同时绑定标题和内容: ```html <Editor v-model:title="articleTitle" v-model:content="articleContent" /> ``` 子组件需分别处理`title`和`content`的更新事件[^4][^3]。 #### 4. **代码示例** **父组件** ```html <template> <UserForm v-model="name" v-model:age="userAge" v-model:email="userEmail" /> </template> ``` **子组件** ```javascript // 接收props props: ['modelValue', 'age', 'email'], // 更新数据 emit('update:modelValue', newName); emit('update:age', newAge); emit('update:email', newEmail); ``` #### 5. **设计思想变化** Vue3通过**参数化v-model**简化了双向绑定的API,解决了Vue2中`v-model`单限制和`.sync`冗余的问题,使代码更统一且可扩展[^5]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值