[ 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.mfbz.cn/a/199075.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C#,数值计算——插值和外推,径向基函数插值(RBF_inversemultiquadric)的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { public class RBF_inversemultiquadric : RBF_fn { private double r02 { get; set; } public RBF_inversemultiquadric(double scale 1.0) { this.r02 Globals.SQR(scale); …

nginx 配置跨域(小皮面板)

本地开发的时候&#xff0c;前端请求后端&#xff0c;后端不能用域名请求&#xff0c;只能用端口模式&#xff0c;在小皮面板的话就是如下配置&#xff1a; 我的测试项目部署&#xff1a; 前端&#xff1a;http://localhost:8082 后端&#xff1a;http://localhost:8081 前端…

【小黑嵌入式系统第十课】μC/OS-III概况——实时操作系统的特点、基本概念(内核任务中断)、与硬件的关系实现

文章目录 一、为什么要学习μC/OS-III二、嵌入式操作系统的发展历史三、实时操作系统的特点四、基本概念1. 前后台系统2. 操作系统3. 实时操作系统&#xff08;RTOS&#xff09;4. 内核5. 任务6. 任务优先级7. 任务切换8. 调度9. 非抢占式&#xff08;合作式&#xff09;内核10…

C陷阱与缺陷——第2章语法陷阱

1. 理解函数声明 硬件将调用首地址为0位置的子例程 (*(void(*)())0)(); 任何C变量的声明都由两部分组成&#xff1a;类型以及一组类似表达式的声明符&#xff0c;声明符从表面看与表达式有些类似&#xff0c;对它求值应该返回一个声明中给定类型的结果。 假定变量fp是一个函…

UData+StarRocks在京东物流的实践 | 京东物流技术团队

1 背景 数据服务与数据分析场景是数据团队在数据应用上两个大的方向&#xff0c;行业内大家有可能会遇到下面的问题&#xff1a; 1.1 数据服务 烟囱式开发模式&#xff1a;每来一个需求开发一个数据服务&#xff0c;数据服务无法复用&#xff0c;难以平台化&#xff0c;技术…

IWDG和WWDG HAL库+cubeMX

一.IWDG 1.原理 启用IWDG后&#xff0c;LSI时钟会自动开启 2.IWDG溢出时间计算 3.IWDG配置步骤 4.HAL库相关函数介绍 HAL_IWDG_Init //使能IWDG&#xff0c;设置预分频系数和重装载值等 HAL_IWDG_Refresh //把重装载寄存器的值重载到计数器中&#xff0c;喂狗typedef str…

上海数字孪生技术推进制造业升级,工业物联网可视化应用加速

上海数字孪生技术推进制造业升级&#xff0c;工业物联网可视化应用加速。数字孪生技术&#xff0c;是从数字模型、数字样机的相关技术发展而来&#xff0c;而对于生产系统的数字孪生又和虚拟制造这一相关技术。数字孪生不是全新技术&#xff0c;它具有建模仿真、虚拟制造、数字…

使用.NET8中的.http文件和终结点资源管理器

本文将以.NET8的模板增加的.http文件为引&#xff0c;介绍 Visual Studio 2022 中的 .http 文件编辑器&#xff0c;这是一个用于测试 ASP.NET Core 项目的强大工具。 文章目录 1. 背景2. HTTP 文件介绍2.1 简介2.2 .http 文件语法3. 在 Visual Studio 中使用3.1 终结点资源管理…

【RESTful API】RESTful接口设计练习

参考: BV1Ps4y1J7Ve ---------------------------------------------------------------------------------------------------------- 一、RESTful框架 常见的有SpringMVC,jersey,play 二、API测试工具 Postman,Insomnia 三、RESTful接口设计练习 3.1 项目准备 构…

使用OSS搭建私有云内网yum仓库的方法

使用OSS搭建私有云内网yum仓库的方法 文字&图片内容已脱敏 #、前几天接到一个搭建内网yum源的任务。刚接到这个任务的时候还是比较头疼的&#xff0c;因为内部有很多VPC。VPC与VPC之间是不互通的&#xff0c;又不能打高速通道&#xff0c;也不可能每个VPC下边都建一个yum…

安全防控 | AIRIOT智能安防管理解决方案

现代社会对安全和便捷性的需求越来越高&#xff0c;特别是在大型商业园区、住宅社区和办公大楼等场所。传统的安防系统往往存在一些痛点: 通行效率问题&#xff1a;传统门禁系统通常导致人员排队等待&#xff0c;降低了通行效率。车辆通行管理不当会导致交通拥堵和停车问题。 …

【古月居《ros入门21讲》学习笔记】15_ROS中的坐标系管理系统

目录 说明&#xff1a; 1. 机器人中的坐标变换 tf功能包能干什么&#xff1f; tf坐标变换如何实现 2. 小海龟跟随实验 安装 ros-melodic-turtle-tf 实验命令 运行效果 说明&#xff1a; 1. 本系列学习笔记基于B站&#xff1a;古月居《ROS入门21讲》课程&#xff0c;且使…

11月28日作业

C环境下实现输入字符串&#xff0c;并判断大小写字母、数字、空格及其他字符个数 #include <iostream>using namespace std;int main() {string str;cout << "请输入一个字符串:" ;getline(cin,str);int num 0,ch 0,CH 0,spa 0,indo 0;for(int i0;…

C语言 移位操作符

<< 左移操作符>> 右移操作符 注&#xff1a;移位操作符的操作数只能是整数。 移位操作符移动的是二进制位。 整数的二进制表示有3种&#xff1a; 原码反码补码 正的整数的原码、反码、补码相同。 负的整数的原码、反码、补码是要计算的。 由负整数原码计算出反…

Linux - 动静态库(上篇)

Linux 当中的 内存管理模块 不管是操作系统对于进程之间的管理&#xff0c;还是 对于文件的访问和修改等等的操作&#xff0c;都是要把数据加载到内存当中的&#xff0c;所以&#xff0c;所有的工作都离不开 内存管理模块。 内存的本质其实是对数据的一种临时存储&#xff0c…

吃火锅(Python)

题目描述 吃火锅 以上图片来自微信朋友圈&#xff1a;这种天气你有什么破事打电话给我基本没用。但是如果你说“吃火锅”&#xff0c;那就厉害了&#xff0c;我们的故事就开始了。 本题要求你实现一个程序&#xff0c;自动检查你朋友给你发来的信息里有没有 chi1 huo3 guo1。…

解析生效探测方法

linux dig命令 1.最常用的查询命令 dig baidu.com2 . 根据记录类型进行查询&#xff0c;比如MX&#xff0c;CNAME&#xff0c;NS&#xff0c;PTR等&#xff0c;只需将类型加在命令后面即可。 dig a.shifen.com ns3 . 指定域名DNS服务器测试解析是否生效的命令&#xff0c;以…

Vscode中字符串报错:Unknown word.cSpell

一. 报错现象 二. 原因 是vscode IDE工具中的插件 Code Spell Checker 会检查字符串的合理性&#xff0c;我们写的中式拼音的字符串&#xff0c;不是一个标准英文单词&#xff0c;就会提示错误&#xff0c;解决方法就是让该插件遇到特定词汇不报错 三. 解决方法

Vue 入门指南:从零开始学习 Vue 的基础知识

&#x1f95d;VUE官方文档 注意&#xff1a; &#x1f4d2;Vue 2 将于 2023 年 12 月 31 日停止维护。详见 Vue 2 延长 LTS。&#x1f4d2;Vue 2 中文文档已迁移至 v2.cn.vuejs.org。&#x1f4d2;想从 Vue 2 升级&#xff1f;请参考迁移指南。 文章目录 &#x1f341;前言&am…

设置MATLAB启动时弹到上次退出时的工作文件夹

前言 每次关机前退出matlab后&#xff0c;下次打开matlab想完成剩余的工作&#xff0c;还需要回忆工作文件夹&#xff0c;或者依据上次打开的m文件之类的点击跳转&#xff0c;一次两次觉得没什么&#xff0c;多了就觉得很麻烦反感&#xff0c;参考官方知乎博主的解答&#xff…