当前位置: 首页 > news >正文

Vue3组件数据双向绑定

目录

组件数据的双向绑定

利用组件通信机制手搓

使用defineModel语法

效果:

defineModel()研究

defineModel的底层机制

defineModel参数

ref选项

ref名字


组件数据的双向绑定

Vue3中的组件数据双向绑定是困扰作者许久的问题,今天因为公司需要,系统的学习了一遍,发现很多有趣的东西,为此在这里记录下来,希望可以帮助到同学们。

目前对于组件数据的双向绑定有两种形式:“利用组件通信机制手搓”(啰嗦,但有助于理解原理)、“使用defineModel语法”(Vue3.4+更新,方便快捷

利用组件通信机制手搓

  • defineProps:接收父组件的数据(正向更新)
  • defineEmits:向父组件传递数据(反向更新)

下面我们用一个“子组件封装一个输入框,父组件调用并实时显示数据”的例子来说明:

子组件(child.vue)

<script setup>
const props = defineProps({label:{type: String,default: "测试名"},modelValue:{type: String,default: "测试值"}
})const emits = defineEmits(['update:modelValue'])</script><template><div><span>{{ props.label }}</span><input type="text" :value="props.modelValue" @input="emits('update:modelValue',$event.target.value)"></div>
</template><style scoped>
</style>

父组件(App.vue)

<script setup>
import { ref } from 'vue';
import child from './components/child.vue';const inputValue = ref('');</script><template>
<div class="container"><child :modelValue="inputValue"@update:modelValue="inputValue = $event"/><p>{{ inputValue }}</p>
</div>
</template><style scoped>
</style>

注意

  • update:modelValue:这是Vue3里约定的更新数据的事件名,格式为“update:prop”,在这个代码中,propmodelValue,因此事件名为“update:modelValue
  • @input:当输入框数据发生变化时,向父组件传递数据

此时,你可能会发现,父组件要使用:“modelValue”和“update:modelValue”两处属性槽,比较啰嗦。那么此时就可以使用Vue3提供给我们的一个“v-model语法糖

<child v-model="inputValue"
/>

上面的代码就相当于:

<child :modelValue="inputValue"@update:modelValue="inputValue = $event"
/>

值得注意的是:“尽管父组件可以使用v-model省略,但是子组件的update:modelValue事件不可省略

使用defineModel语法

使用defineModel语法要求Vue版本大于3.4

子组件(child.vue)

<script setup>
const model = defineModel()
const props = defineProps({label:{type: String,default: "测试名"}
})
</script><template><div><span>{{ props.label }}</span><input type="text" v-model="model" /></div>
</template><style scoped>
</style>

父组件(App.vue)

<script setup>
import { ref } from 'vue';
import child from './components/child.vue';const inputValue = ref('');</script><template>
<div class="container"><child v-model="inputValue"/><p>{{ inputValue }}</p>
</div>
</template><style scoped>
</style>

效果:

可以看到使用defineModel()可以非常轻松地实现组件间的双向数据绑定

defineModel()研究

defineModel的底层机制

defineModel返回的值是一个ref

defineModel是一个便利宏,编译器会解析为:

  • 一个名为modelValue的prop,本地ref的值与其同步
  • 一个名为update:modelValue的事件,当本地ref的值发生变更时修改

大白话

  • defineModel返回一个ref,当这个ref值变化时,会自动调用defineModel解析的update:modelValue事件
  • defineModel解析的update:modelValue事件会传递当前ref的值

defineModel参数

ref选项

defineModel可以接收一个“对象”来配置ref的一些选项

// 该v-model必填
const model = defineModel({required: true})
// 默认值
const model = defineModel({default: 0})

注意

  • 当给model绑定一个“default默认值”时,如果父组件传入的v-model参数有值,那么该默认值会被顶替
  • 如果父组件传入的v-model参数为空,那么该默认值会生效,但父组件与子组件之间不同步,此时父组件值为空,子组件值为默认值

子组件(child.vue)

<script setup>
const model = defineModel({default: "123"})
const props = defineProps({label:{type: String,default: "测试名"}
})
</script>
<template><div><span>{{ props.label }}</span><input type="text" v-model="model"/></div>
</template>
<style scoped>
</style>

父组件(parent.vue)

<script setup>
import { ref } from 'vue';
import child from './components/child.vue';const titleValue = ref();</script><template>
<div class="container"><child v-model="titleValue"/><p>{{ titleValue }}</p>
</div>
</template><style scoped>
</style>

效果

当组件初次载入时,此时父组件和子组件之间的数据不同步,当修改子组件数据后,父子组件数据同步

原因

  • 组件载入时,父组件向子组件传参数值,参数值为空,因此子组件默认值生效,子组件参数值为123
  • 子组件默认值生效后,没有向父组件传递参数值,此时父组件参数值仍为空
  • 当子组件参数值修改后,触发底层update:modelValue方法,向父组件传递参数值
  • 父组件接收到参数值,修改本地参数值,实现数据同步

ref名字

defineModel可以接收一个“字符串”作为返回ref的名字,利用该特性我们可以同时绑定多个v-model

用法:

// 指定一个title名字
const model = defineModel('title')
// 父组件调用时,指定传给名为title的ref
<child v-model:title="inputValue"
/>

多个v-model绑定:

子组件(child.vue)

<script setup>
const modelTitle = defineModel('title')
const modelDescription = defineModel('description')
const props = defineProps({label:{type: String,default: "测试名"}
})
</script>
<template><div><span>{{ props.label }}</span><input type="text" v-model="modelTitle" style="margin-right: 1rem"/><input type="text" v-model="modelDescription" /></div>
</template>
<style scoped>
</style>

父组件(parent.vue)

<script setup>
import { ref } from 'vue';
import child from './components/child.vue';const titleValue = ref('');
const descriptionValue = ref('');</script><template>
<div class="container"><child v-model:title="titleValue"v-model:description="descriptionValue"/><p>{{ titleValue }}</p><p>{{ descriptionValue }}</p>
</div>
</template><style scoped>
</style>

效果


文章转载自:

http://HeRRzT6d.fynkt.cn
http://LCzZ5iRY.fynkt.cn
http://MCStKxLk.fynkt.cn
http://epv1euhi.fynkt.cn
http://yD7jf3gX.fynkt.cn
http://tESoTuzc.fynkt.cn
http://BVFtTvZl.fynkt.cn
http://RyCQ0fsE.fynkt.cn
http://9zt1S2R8.fynkt.cn
http://WqAkW8Xg.fynkt.cn
http://YiP2DfgZ.fynkt.cn
http://uXYqOZFB.fynkt.cn
http://dlgLU2n1.fynkt.cn
http://q2ESOgq9.fynkt.cn
http://wjpYQIS1.fynkt.cn
http://qXkeZ8x7.fynkt.cn
http://iBfxiIji.fynkt.cn
http://kMK4ohnx.fynkt.cn
http://8mETR0ph.fynkt.cn
http://1CfOlpQB.fynkt.cn
http://wlrW9UYt.fynkt.cn
http://ul2XsKWT.fynkt.cn
http://3jZzZl2g.fynkt.cn
http://TWFD7unm.fynkt.cn
http://uItCAiPJ.fynkt.cn
http://m7QctyAI.fynkt.cn
http://18OZ4X7u.fynkt.cn
http://nQTbhb85.fynkt.cn
http://N5FfIVyP.fynkt.cn
http://osXUmqRa.fynkt.cn
http://www.dtcms.com/a/380814.html

相关文章:

  • 死锁检测算法的实现方式-Java
  • 前端设计模式全解(23 种)
  • 110.for循环执行顺序
  • 【Git】merge 分类
  • 2025最新超详细FreeRTOS入门教程:第十四章 FreeRTOS空闲任务与钩子函数
  • Parasoft 斩获 AutoSec 2025 优秀汽车 AI 测试创新方案奖
  • MATLAB3-2数据存储-台大郭彦甫
  • Spring Cloud Gateway基础复习
  • 【scikit-learn系列文章】
  • 后端编程开发路径:从入门到精通的系统性探索
  • 单片机esp32 基础调试 联网fetch http.begin(targetUrl);
  • rust语言 (1.88) egui (0.32.2) 学习笔记(逐行注释)(二十八)使用图片控件显示图片
  • 补 json的作用
  • windows 装虚拟机
  • mybatisplus 自定义注解和拦截器动态修改sql,实现数据权限控制
  • bat 批处理实现 FFmpeg 命令拼接 png 为 TextAtlas
  • 01数据结构-B树练习及B+树特点
  • 现代化私有相册rgallery
  • 第十九篇|东京世界日本语学校的结构数据建模:制度函数、能力矩阵与升学图谱
  • 装饰你的README
  • 嵌入式Linux学习_rk3588移植无线网卡驱动
  • 【Spring】原理解析:Spring Boot 自动配置进阶探索与优化策略
  • Rust : 关于Deref
  • domain_auto_trans,source_domain,untrusted_app
  • prometheus安装部署与alertmanager邮箱告警
  • 【数据可视化-112】使用PyEcharts绘制TreeMap(矩形树图)完全指南及电商销售数据TreeMap绘制实战
  • rust语言 (1.88) 学习笔记:客户端和服务器端同在一个项目中
  • Java多线程分块下载文件
  • 玩转deepseek之自动出试卷可直接导出word
  • 智慧城管源码,java版城管综合执法监督系统微服务源码