[ Vue3 ] 三种方式实现组件数据双向绑定

Vue3 三种方式实现组件数据双向绑定

Vue 中,组件数据双向绑定是一项非常重要的特性,它使得我们能够轻松地在组件中处理数据的变化并将其同步到视图

比如我们想要在父组件中修改数据能够同步给子组件,并且子组件修改数据也能同步给父组件,使他们数据一方发生变化,则双方都发生改变。

实现组件数据双向绑定有三种写法分别是 常规写法v-modeldefineModel,下面给大家一一演示

常规写法

在点击父组件按钮时修改数据并同步给子组件

<script setup lang="ts">
import { ref } from 'vue';
import Hello from './components/Hello.vue';const data = ref("Hello World")// 通过调用该事件完成修改数据的操作
const changeData = (value: string) => {data.value = value
}
</script><template><h1>{{ data }}</h1><button @click="data = 'Hello Vue3'">修改子组件的数据</button><!-- 简写:<Hello :data="data" @update="data = $event" /> --><Hello :data="data" @update="changeData" />
</template>

点击子组件中的按钮触发父组件的自定义事件 update 绑定的 changeData 方法,并将参数 你好,世界! 传递给父组件的方法: changeData 从而实现更改父组件的数据

<script setup lang="ts">
const props = defineProps<{ data: string }>()
const emit = defineEmits<(e: "update", value: string) => void>()
</script><template><h1>{{ data }}</h1><button @click="emit('update', '你好, 世界!')">修改父组件的数据</button>
</template>

可以发现这种写法非常繁琐,子组件修改数据还要通过触发事件来完成

v-model

Vue3 中,使用 v-model 指令来实现组件数据的双向绑定非常简单。我们可以在组件中使用 v-model 指令来绑定一个值,并且在组件内部可以直接操作这个值。

接下来这种写法才是 Vue 主流的方式:

<script setup lang="ts">
import { ref } from 'vue';
import Hello from './components/Hello.vue';const data = ref("Hello World")
</script><template><h1>{{ data }}</h1><button @click="data = 'Hello Vue3'">修改子组件的数据</button><!-- 核心代码 --><Hello v-model="data" />
</template>
  1. 在子组件中我们将数据以 modelValue 命名来接收(固定命名)

  2. defineEmits 定义一个修改数据的事件:(e: "update:modelValue", value: string) => void

  3. 通过触发 emit('update:modelValue', '你好, 世界!') 来实现数据的更新操作

<script setup lang="ts">
const props = defineProps<{ modelValue: string }>()
const emit = defineEmits<(e: "update:modelValue", value: string) => void>()
</script><template><h1>{{ modelValue }}</h1><button @click="emit('update:modelValue', '你好, 世界!')">修改父组件的数据</button>
</template>

接下来想必大家就会有疑惑了,如果是多个数据需要双向绑定该怎么做呢?其实也很简单:

<script setup lang="ts">
import { ref } from 'vue';
import Hello from './components/Hello.vue';const data1 = ref("Hello World")
const data2 = ref("Hello World")
</script><template><h1>{{ data1 }}</h1><h1>{{ data2 }}</h1><button @click="data1 = 'Hello Vue3'">修改子组件的数据</button><button @click="data2 = 'Hello TypeScript'">修改子组件的数据</button><!-- 核心代码 --><Hello v-model:data1="data1" v-model:data2="data2" />
</template>
<script setup lang="ts">
const props = defineProps<{ data1: string, data2: string }>()
const emit = defineEmits<{ (e: "update:data1", value: string): void, (e: "update:data2", value: string): void }>()
</script><template><h1>{{ data1 }}</h1><h1>{{ data2 }}</h1><button @click="emit('update:data1', '你好, 世界!')">修改父组件的数据</button><button @click="emit('update:data2', '你好, 世界!')">修改父组件的数据</button>
</template>

对比一下常规的写法,可以发现不必再通过手动绑定事件就可以达到双向绑定的需求。

而常规写法其实就是这种写法的实现原理

defineModel

学习了上述两种写法后,接下来这种写法你一定会爱不释手,话不多说直接代码演示:

<script setup lang="ts">
import { ref } from 'vue';
import Hello from './components/Hello.vue';const data = ref("Hello World")
</script><template><h1>{{ data }}</h1><button @click="data = 'Hello Vue3'">修改子组件的数据</button><!-- 核心代码 --><Hello v-model="data" />
</template>
<script setup lang="ts">
import { defineModel } from 'vue'
const modelValue = defineModel()
</script><template><h1>{{ modelValue }}</h1><button @click="modelValue = '你好, 世界!'">修改父组件的数据</button>
</template>

当然,如果想要实现多个双向数据绑定可以这么做:

<script setup lang="ts">
import { ref } from 'vue';
import Hello from './components/Hello.vue';const data1 = ref("Hello World")
const data2 = ref("Hello World")
</script><template><h1>{{ data1 }}</h1><h1>{{ data2 }}</h1><button @click="data1 = 'Hello Vue3'">修改子组件的数据</button><button @click="data2 = 'Hello TypeScript'">修改子组件的数据</button><!-- 核心代码 --><Hello v-model:data1="data1" v-model:data2="data2" />
</template>
<script setup lang="ts">
import { defineModel } from 'vue'
const data1 = defineModel("data1")
const data2 = defineModel("data2")
</script><template><h1>{{ data1 }}</h1><h1>{{ data2 }}</h1><button @click="data1 = '你好, 世界!'">修改父组件的数据</button><button @click="data2 = '你好, 世界!'">修改父组件的数据</button>
</template>

使用该语法糖可以直接调用 defineModel 拿到父组件传递的数据,不需要再使用 defineEmitsdefineProps 就可以操作数据,告别繁琐的组件双向数据绑定。

注意: 该方式仅支持 Vue3.2.0 及以上版本

目前该方式处于Vue官方实验阶段,所以在控制台会出现以下警告:

defineModel() is a compiler-hint helper that is only usable inside <script setup> of a single file component. Its arguments should be compiled away and passing it at runtime has no effect

解决它的办法也很简单,在 vite.config.ts 文件中配置如下代码即可:

export default defineConfig({plugins: [// 核心代码vue({script: {defineModel: true,},}),]
});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/180434.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Make Pixels Dance: High-Dynamic Video Generation论文解析

高动态视频生成的新进展 Make Pixels Dance: High-Dynamic Video Generation高动态视频生成的新进展前言视频生成模式摘要论文十问实验数据集定量评估指标消融研究 训练和推理技巧训练技术推理技术 更多的应用 Make Pixels Dance: High-Dynamic Video Generation 高动态视频生…

VBA技术资料MF87:创建固定顺序名称的一组文件夹

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。我的教程一共九套&#xff0c;分为初级、中级、高级三大部分。是对VBA的系统讲解&#xff0c;从简单的入门&#xff0c;到…

gRPC Java、Go、PHP使用例子

文章目录 1、Protocol Buffers定义接口1.1、编写接口服务1.2、Protobuf基础数据类型 2、服务器端实现2.1、生成gRPC服务类2.2、Java服务器端实现 3、java、go、php客户端实现3.1、Java客户端实现3.2、Go客户端实现3.3、PHP客户端实现 4、运行效果 本文例子是在Window平台测试&a…

Unity UGUI图片锯齿严重怎么解决

在开发的时候&#xff0c;发现图片锯齿严重&#xff0c;打包到移动端或者在编辑器都这样&#xff0c;如下图 原因&#xff1a; 查了一些资料&#xff0c;找到了原因如下&#xff1a;关于为什么会发生这种情况&#xff1a;看起来你的源资源比你在屏幕上显示的大小大得多。所以当…

【迅搜04】索引配置(一)加载配置文件以及服务端配置

索引配置&#xff08;一&#xff09;加载配置文件以及服务端配置 对于一个搜索引擎来说&#xff0c;索引配置是非常重要&#xff0c;并且也是非常核心的内容。在 XS 中&#xff0c;我们的索引配置是通过一个配置文件来实现的。在前两篇文章的测试中&#xff0c;我们使用了一个叫…

深入浅出 Vue 中的插槽 slot

深入浅出 Vue 中的插槽 slot start 最近被问到好几次 Vue 中的插槽相关知识&#xff0c;掌握的还是有些不全面。抱着重新学习的心态&#xff0c;写这篇博客。首先对基础知识做一个回顾&#xff0c;然后再对源码实现做一个学习。作者&#xff1a;番茄编写时间&#xff1a;2023…

初始本地仓库推送到远程仓库-git

背景&#xff08;问题描述&#xff09; 下面的git的操作符合的情况是&#xff1a; ①本地初始化一个仓库&#xff0c;但是还没有和远程仓库相关联&#xff1b; ②远程仓库也刚刚创建&#xff0c;里面啥也没有 然后目前就想将本地的仓库的内容和远程仓库相关联并推送到远程仓…

Linux配置SFTP用户

0. 背景 Linux机器上已有路径/data/tomcat/apache-tomcat-8.5.96/webapps/webroot,需要在该路径之下配置一个sftp用户账户对外暴露给业务人员使用。 下面是相关配置&#xff1a; SFTP 用户名&#xff1a;iios SFTP主目录&#xff1a;/data/tomcat/apache-tomcat-8.5.96/weba…

STM32_10(I2C)

I2C通信 I2C&#xff08;Inter IC Bus&#xff09;是由Philips公司开发的一种通用数据总线两根通信线&#xff1a;SCL&#xff08;Serial Clock&#xff09;、SDA&#xff08;Serial Data&#xff09;同步&#xff0c;半双工带数据应答支持总线挂载多设备&#xff08;一主多从…

QAC支持的静态度量属性

上面介绍了Coverity支持的12个度量属性&#xff0c;下面我们看看QAC这款工具支持的度量属性。下面分成3类&#xff0c;函数度量、文件度量和类度量。 函数度量指标不多&#xff0c;一共有8个。 文件度量度量指标一共10个&#xff0c;如下表。 类度量指标一个8个&#xff0c;如…

事务一致性

数据库的并发控制与封锁 并发控制 并发控制是确保数据库在多个用户同时访问时保持数据一致性和完整性的机制。主要的并发控制技术包括&#xff1a; 锁定&#xff08;Locking&#xff09;&#xff1a;数据库通过对数据项加锁来限制对它们的访问。锁可以是共享的&#xff08;读…

python实现C++简易自动压行

突发奇想&#xff0c;想要将自己的c压行之后交上去。但是苦于手动压行效率太低&#xff0c;在网上搜索压行网站没有找到&#xff0c;突然发现压行不就是检查检查去个换行符吗。于是心血来潮&#xff0c;用python实现了一个简易压行程序。 首先&#xff0c;宏定义等带#的文件不…

正则表达式及文本三剑客grep,awk,sed

目录 正则表达式 前瞻 代表字符 表示次数 位置锚定 分组或其他 grep 选项 范例 awk 前瞻 awk常见的内置变量 范例 sed 前瞻 sed格式 范例 搜索替代 格式 范例 分组后项引用 格式 范例 正则表达式 前瞻 通配符&#xff1a;匹配的是文件名 正则表达式&a…

Windows10免安装PostgreSQL

1. PostgreSQL简介2. 下载3. 安装环境4. 安装 4.1. 初始化数据库4.2. 启动数据库4.3. 注册服务4.3. 卸载服务 1. PostgreSQL简介 PostgreSQL 是一种特性非常齐全的自由软件的对象-关系型数据库管理系统&#xff0c;是以加州大学计算机系开发的 POSTGRES 4.2版本为基础的对象关…

java开发需要掌握的maven相关知识和Junit单元测试

maven简介 什么是maven&#xff1a; maven是一款管理和构建java项目的工具&#xff0c;是apache旗下的一个开源项目。 maven的作用&#xff1a; 依赖管理&#xff1a; 方便快捷的管理项目依赖的资源&#xff08;jar包&#xff09;。 项目构建&#xff1a; 标准化的跨平台&#…

开发知识点-CSS样式

CSS样式 fontCSS 外边距 —— 围绕在元素边框的空白区域# linear-gradient() ——创建一个线性渐变的 "图像"# transform ——旋转 元素![在这里插入图片描述](https://img-blog.csdnimg.cn/20191204100321698.png)# rotate() [旋转] # 边框 (border) —— 围绕元素内…

[传智杯 决赛] 三元组

题目描述 给定一个长度为 n 的数列 a&#xff0c;对于一个有序整数三元组 (i,j,k)&#xff0c;若其满足 1≤i≤j≤k≤n 并且 ai​aj​ak​&#xff0c;则我们称这个三元组是「传智的」。 现在请你计算&#xff0c;有多少有序整数三元组是传智的。 输入格式 本题单测试点内有…

计算机毕业设计php+bootstrap小区物业管理系统

意义&#xff1a;随着我国经济的发展和人们生活水平的提高&#xff0c;住宅小区已经成为人们居住的主流&#xff0c;人们生活质量提高的同时&#xff0c;对小区物业管理的要求也越来越高&#xff0c;诸如对小区的维修维护&#xff0c;甚至对各项投诉都要求小区管理者做得好&…

百度离线3.0的一些功能的实现

案例: 设置覆盖物标注提示文字: <script>// 百度地图API功能var map new BMap.Map("map",{ mapType: BMAP_HYBRID_MAP }); var point new BMap.Point(120.55294, 41.665515); // 创建Map实例map.centerAndZoom(point, 18); // 初始化地图,设置中心点坐标…

人工智能-优化算法之梯度下降

梯度下降 尽管梯度下降&#xff08;gradient descent&#xff09;很少直接用于深度学习&#xff0c; 但了解它是理解下一节随机梯度下降算法的关键。 例如&#xff0c;由于学习率过大&#xff0c;优化问题可能会发散&#xff0c;这种现象早已在梯度下降中出现。 同样地&#x…