vue3学习教程第三节(v-model 执行原理)

特殊说明: 以下vue3语法是基于 3.4之前版本进行使用的,3.4之后的版本 引入了 defineModel 宏,后续会介绍defineModel

1、vue3 与vue2 中v-model区别
vue3 中v-model绑定的不再是value,而是modelValue,接收的方法也不再是input,而是update:modelValue
vue2 中v-model的主要原因是由于value和input事件可能另有它用,比如select、textarea,select选择框绑定的是checked,而不是value,同样接受事件也不是input,而是change
如下图:
在这里插入图片描述

2、v3 v2 中绑定单个值:

2.1 vue3中双向绑定单个值,以及自定义绑定值时候
v-model 在原生input上使用
父组件

<template>
  <input v-model="myV3Vale" />
   <!-- 编译之后等价于 -->
  <input :value="myV3Vale" @input="myV3Vale = $event.target.value"/>
  <!-- 引用组件中 // 默认传值是 modelVale-->
  <my-son-com 
  :modelValue="myV3Vale"   
  :otherPropField="otherPropField"
  @update:modelValue="newValue => myV3Vale = newValue"
  @update:otherPropField="newValue => myV3Vale = newValue"
  ></my-son-com>
</template>

子组件

// 以下为:MySonCom.vue
<template>
   <input
    :value="props.modelValue"
    @input="emit('update:modelValue', $event.target.value)"
  />
</template>
<script setup>
// 默认传参必须是modelValue,事件必须是update:modelValue,在子组件中如下:
const props = defineProps({
  modelValue: String
})
const emits = defineEmits(["update:modelValue"])
const update = (e) => {
  emits("update:modelValue", e.target.value)
}
//多个参数时 传递额外参数 otherPropField 必须是如下:v-model:otherPropField,对应的事件是update:otherPropField
const otherProp = defineProps({
  otherPropField: String
})
const othersEmits = defineEmits(["update:otherPropField"])
const otherUpdate = (e) => {
  emits("update:otherPropField", e.target.value)
}
</script>

2.2、v2 中绑定单个值、多个值
父组件

<template>
  <!-- 默认传值是 value -->
  <my-com-v2 v-model="myV2Value" v-bind:otherField.sync="otherField"/>
  // 等价与
  <my-com-v2 :value="myV2Value" @input="myV2Value = $event"/>
  
  // 绑定额外参数 使用 .sync
  <my-com-v2  v-bind:otherField.sync="otherField"/>
  <my-com-v2  v-bind:otherField="otherField" v-on:update:otherField="otherField = $event"/>
  <!-- 在组件中 -->
</template>

子组件 MyComV2.vue

<template>
  <input type="text" :value="myV2Value" @input="inputChange">
</template>
<script>
export default {
  name: 'MyComV2',
  props: {
    value: {
      type: String,
      default: ''
    },
    otherField: {
      type: String,
      default: '其他属性'
    }
  },
  methods: {
    inputChange(e) {
      // v2中双向绑定触发只能是 input 事件
      this.$emit('input', e.target.value)
    }
  }
}
</script>

3.vue3 中绑定多个值 基于3.4版本之前,

父组件
<template>
  <my-son-com v-model:name="name" v-model:person="person"></my-son-com>
</template>>
<script setup>
import { ref, reactive} from 'vue'
const name = ref('Andy')
const person = reactive({
  age: 18,
  sex: 'MEN'
})
</script>

子组件 MySonCom.vue
建议使用 setup 语法糖,而不是使用 setup() {} 函数

<template>
  <input type="text" :value="name" @input="$emit('update:name', $event.target.value)">
  <input type="text" :value="person.age" @input="$emit('update:person', $event.target.value)">
</template>
<script setup>
defineProps({
  name: String,
  person: Object
})
defineEmits(['update:name', 'update:person'])
</script>

4.vue3 中不在使用.sync 替代方案是 modelValue底层更新逻辑

v3常用修饰符有 .lazy, .number, .trim
<template>
  默认是每次 input 事件之后更新数据,而添加lazy之后,变成每次change事件之后才能更新数据;
  <input type="text" v-model.lazy="name">
  .number 将用户输入的内容转换为 number 数字,如果无法转换为number类型的数字,则会视为无效的输入;
  <input type="number" v-model.number="age">
  .trim 将用户输入内容 两端的空格 自动去除;
  <input type="text" v-model.trim="name">
</template>
### Vue.js 中 `v-model` 的双向绑定实现机制 #### 一、概念理解 在 Vue.js 中,`v-model` 是一种用于创建双向数据绑定的语法糖。它简化了表单输入元素与组件状态之间的同步操作[^2]。 #### 二、工作流程概述 当使用 `v-model` 绑定到一个 input 元素上时,在内部会转换成两个部分:一个是将 value 属性绑定到指定变量;另一个是在 input 事件触发时更新这个变量的值。这种设计使得开发者能够轻松地管理表单项的状态而无需手动编写大量的监听器代码[^4]。 #### 三、具体实现过程 ##### (一)初始化阶段 对于普通的 HTML 表单控件来说(如 `<input>`),`v-model` 主要通过设置其初始值来完成第一次渲染: ```html <input v-model="message"> ``` 上述语句会被编译为如下形式: ```html <input :value="message" @input="updateMessage"> ``` 其中 `@input` 监听用户的输入行为并调用相应的处理函数 `updateMessage()` 来修改对应的 data property —— 即实现了从 view 到 model 方向上的同步[^1]。 ##### (二)响应式更新逻辑 每当用户交互引起 DOM 节点发生变化时——比如键入新的字符,Vue 就会捕获这些变动并通过事件处理器执行必要的动作。此时框架利用自身的观察者模式(Observer Pattern),确保任何依赖于该属性的地方都能及时得到通知并作出相应调整[^3]。 为了达到这一目的,Vue 使用了一个叫做 Dep (Dependency) 的类来追踪谁订阅了自己的变更消息以及如何分发它们。每当某个 reactive object 发生改变之后,所有关联着它的 watcher 都会被激活进而重新计算视图中的相关内容。 ##### (三)自定义组件支持 除了原生标签外,`v-model` 还允许应用于自定义组件之上。在这种情况下,默认的行为是基于名为 `value` 的 prop 和名为 `input` 的 event 构建起一套类似的通信协议。不过也可以通过 `.sync`修饰符 或 显式声明 model options 来定制化这套机制以适应更复杂的需求场景。 ```javascript // 自定义组件内模拟 v-model 支持 export default { props: [&#39;value&#39;], methods: { emitValueChange(newValue){ this.$emit(&#39;input&#39;, newValue); } }, template: ` <div> <!-- ... --> <button @click="emitValueChange(someNewValue)">Update Value</button> <!-- ... --> </div>` } ``` #### 四、总结 综上所述,`v-model` 不仅提供了一种简洁的方式来表达双向绑定关系,而且背后隐藏着一系列精心设计的技术细节保障其实现效果。借助 Vue 内置的强大响应式引擎,即使面对复杂的 UI 更新需求也能保持高效流畅的表现。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刺客-Andy

努力将爱好变成更有价值的事物

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值