vue学习八

十七 组件通信方式

1 props

父传子

//父组件
<script setup>//book来源省略import Subview1 from './Subview1.vue';function updatebook(updatetimes){book.value.updatetimes = updatetimes}
</script>
<template><Subview1 :book="book" :updatebook=updatebook></Subview1>
</template>//子组件
<script setup>import { ref } from 'vue'let updatetimes = ref(0)//修改次数defineProps(['book','updatebook'])
</script>
<template><p>{{ book }}</p><p><button @click="updatebook(updatetimes)">updateprice</button> </p>
</template>

 点击updateprice前

 点击updateprice后

例子中列表来源于mockjs,点击详细这则设置book为选中的列表中对应位置的值,图里选中的是第一个。

点击详细后,父组件将book传给子组件。

点击updateprice后,子组件将其定义的变量updatetimes传给父组件。

父组件传给子组件,依靠子组件 defineProps设置的变量。

子组件传给父组件,依靠子组件 defineProps设置的方法,该方法体在父组件中设置。

2 自定义事件

用于子向父传数据。

子组件使用defineEmits定义事件,使用emit()触发事件。

父组件对于定义的事件绑定相应方法

//父组件
<script setup>
//list book 来源省略
function updatebook2(book){//修改父组件list中的值list[list_index]= book
} 
</script>
<template><Subview1 :book="book" :updatebook="updatebook" @update:book="updatebook2"></Subview1> 
</template>//子组件
<script setup>
import { ref } from 'vue'
let updatetimes = ref(0)//修改次数
defineProps(['book','updatebook'])
//定义事件
let emit = defineEmits(['update:book'])
//修改价格
function updateprice(book){book.price = book.price + 1updatetimes.value++book.updatetimes = updatetimesemit('update:book',book)
}
</script>
<template><p><button @click="updateprice(book)">updateprice</button> </p>
</template>

 点击修改前

 点击两次修改后

子组件定义事件,可随时设置事件调用。

父组件设置子组件事件绑定的对应回调。

子组件事件触发后,会执行父类定义的回调。

官方推荐:

父组件中可以使用 kebab-case 形式来监听。

实际就是例子中update:book变成update-book

组件中自定义事件也支持修饰符。

组件触发的事件没有冒泡机制,只能监听直接子组件触发的事件,即平级的和跨层的emit监听不到。

3 mitt

可实现任意组件通信。

流程:定义事件并绑定操作->中间件做事件管理->触发事件触发对应操作。

定义:项目名\src\utils\emitter.js

import mitt from "mitt"
const emitter = mitt()export default emitter

父组件

<script setup> 
……
import Subview1 from './Subview1.vue';
import Subview2 from './Subview2.vue';
……
function updatebook2(book){list[list_index]= book
} 
</script>
<template><div class="main"><h1>View 10</h1><h3>books</h3><div v-for="item in list" :key="item.id" class="book_item"><div class="img"> <img :src="item.cover" alt="item.name"></div><div class="info">   <p>name:{{ item.name }}</p><p>price:{{item.price}}</p></div><div><button @click="showbook(item.id)">详细</button>  </div></div><div class="sub" v-show="book"><Subview1 :book="book" :updatebook="updatebook" @update:book="updatebook2"></Subview1> </div><div class="sub"><Subview2></Subview2></div></div>
</template>  

 Subview1

<script setup>
import { ref } from 'vue'
import mitt from '@/utils/emitter.js';
let updatetimes = ref(0)//修改次数
defineProps(['book','updatebook'])
let emit = defineEmits(['update:book'])
//修改价格
function updateprice(book){book.price = book.price + 1updatetimes.value++book.updatetimes = updatetimesemit('update:book',book)
}
</script>
<template><div ><h2>Subview1</h2><p>{{ book }}</p><p>updatetimes:{{updatetimes}}</p><!-- <p><button @click="updatebook(updatetimes)">updateprice</button> </p> --><p><button @click="updateprice(book)">updateprice</button>&nbsp;<button @click="mitt.emit('buy-book',book)">buybook</button> </p></div>
</template>  
<style scoped>
</style>

Subview2

<script setup>
import { reactive } from 'vue'
import mitt from '@/utils/emitter.js';
let buybooks =reactive([])
mitt.on('buy-book',(book)=>{let hasbook =falsefor (var value of buybooks) {if(value.id===book.id){value.num++;hasbook = true;break;}}if(!hasbook){book.num=1;buybooks.push(book)}
})</script>
<template><div ><h2>Subview2</h2><div v-show="buybooks.length>0"><p>buy books</p><div v-for="(item,key) in buybooks" :key="key"><!-- {{key}} -->{{ item.name }}&nbsp;&nbsp;{{ item.num }}x{{item.price}} = {{item.price*item.num}} </div></div></div> 
</template>

 根据样例,父类展示两个子类,子类中引用mitt定义文件。

Subview1中触发事件,需要defineEmits定义事件名,使用mitte.emit(时间名,参数)调用。

Subview2中接收事件,使用mitt.on(事件名,回调)。

调用mitt.on()后最好再调用mitt.off()进行解绑。

onUnmounted(()=>{mitt.off(事件名)
})

 上图为点击一次buybook效果。

 上图为点击一次updateprice之后再点击一次buybook效果。

4 v-model

用与变量双向绑定。

<script setup>
……
let book =ref(false)
……
function inputaction($event){book.value.name = $event.target.value
}
function inputaction1(a,$event){book.value.name = a+"_"+$event.target.value
}
</script>
<template><div>book:<input type="text" :value="book.name" @input="inputaction"><br>book: <input type="text" v-model="book.name"><br>book:<input type="text" :value="book.name" @input="inputaction1(1,$event)"></div>
</template>

 例子中input两种帮定效果一样。

原始方式就是绑定变量(此时是单向绑定)之后,再绑定方法(此时是双向绑定)用于修改变量。

v-model命令直接可以双向绑定变量。

绑定事件不设置参数时参数默认$event,设置参数时传递$event需要写在参数列表中。

使用在组件中就是实现组件通信,跨组件变量的双向绑定。

若不使用v-model就是在组件中设置props和emits:

//父组件
<Subview :bookname="book.name" @update:bookname="book.name=$event"></Subview>//子组件
defineProps(["bookname"])
defineEmits(["update:bookname"])<input type="text" :value="bookname" @input="$emit('update:bookname',$event.target.value)">

 使用v-model后:

//父类
<Subview2 v-model="book.price"></Subview2>//子类
defineProps(["modelValue"])
defineEmits(["update:modelValue"])bookprice:<input type="text" :value="modelValue" @input="$emit('update:modelValue',$event.target.value)">

 子组件中modelValue和update:modelValue是固定的。

5.definemodel

vue3.4提供的宏definemodel,可以简化v-model中组件的代码。

父组件

<Subview1 v-model="book.name" v-model:bookprice="book.price"></Subview1> 

子组件

let [bookname] = defineModel()  
let bookprice = defineModel("bookprice")
function changename($event){bookprice.value =$event.target.value
} <input type="text" :value="bookprice" @input="changename">

 父附件可以设置多个v-model,子组件可以解构defineModel或者直接使用。

defineModel生命一个model prop,所以修改方法和prop一样。

6 $attrs

用于当前组件的父组件和子组件传数据。

父组件传给子组件的参数中,若子组件未接收,则存在$attrs。

可以将$attrs传给子组件,子组件再接收。

父类

let test=ref("test")<Subview2 :bookname="book.name" :test="test"></Subview2>

子类

//Subview2defineProps(["bookname"])<Subview3 v-bind="$attrs"></Subview3>    //Subview3<script setup> 
defineProps(["test"])
</script><template><h3>Subview3</h3><p>test: {{ test }}</p>
</template>

6 $refs

用于获取和修改子组件暴露的数据。

子组件需要使用defineExpose暴露变量。

父组件在子组件上设置ref,用于$refs获取。

父组件

function add_updatetimes(values){console.log(values)console.log(values['sub1'].updatetimes)values['sub1'].updatetimes+=1
}<button @click="add_updatetimes($refs)">add updatetimes</button><Subview1 ref="sub1"></Subview1> 

子组件

let updatetimes = ref(0)
defineExpose({updatetimes})<p>updatetimes:{{updatetimes}}</p>

 console输出

 

点击add updatetimes 后

 一个父组件可以有多个子组件。

7 $parent

用于子组件获取和修改父组件暴露的数据。

父组件暴露数据后,子组件通过$parent获取和修改。

父组件

let test=ref("test")
defineExpose({test})

 子组件

function updatetest(parent){console.log(parent)parent.test = "subview1"
}<button @click="updatetest($parent)">update test</button> 

 console输出

一个子组件只能由一个父组件,即只能获取最直接的调用其的父附件。

跨组件调用$parent获取不到对应数据。

8 inject&provide

父组件通过provide向之后的子组件传递数据,可跨组件。

子组件通过inject获取父组件传递的数据,可跨组件。

父组件在设置provide,可设置方法,在子组件中可通过改方法向父组件通讯。

父组件

let test1=ref("test1")
function changetest(value){test1.value+="."+value
}
provide("view10_test",{test1,changetest})

子组件

let {test1,changetest} = inject("view10_test","默认值")<p>test1: {{ test1 }}
</p><button @click="changetest('new test')" >change test</button>

点击change test后

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

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

相关文章

51单片机的寻址方式(完整)

目录 一、立即数寻址 二、直接寻址 三、寄存器寻址 四、寄存器间接寻址 五、变址寻址 六、位寻址 七、指令寻址 &#xff08;一&#xff09;绝对寻址 &#xff08;二&#xff09;相对寻址 在 51 单片机中&#xff0c;寻址方式是指在执行指令时&#xff0c;CPU 寻找操作…

每日一题:动态规划

如题&#xff08;基础题&#xff09;&#xff1a; 经典的爬楼梯问题&#xff0c;先从递归想起&#xff1b; class Solution { public:int climbStairs(int n) {if(n1)return 1;if(n2)return 2;return climbStairs(n-1)climbStairs(n-2);} }; 之后可以想办法&#xff08;如哈希…

【论文阅读】FairCLIP - 医疗视觉语言学习中的公平性提升

FairCLIP - 医疗视觉语言学习中的公平性提升 1.研究背景与动机2.核心贡献3.方法论细节4.实验结果与洞见5.总结 FairCLIP: Harnessing Fairness in Vision-Language Learning FairCLIP - 医疗视觉语言学习中的公平性提升 Accepted by CVPR2024 github:链接 1.研究背景与动机…

Linux 入门:权限的认识和学习

目录 一.shell命令以及运行原理 二.Linux权限的概念 1.Linux下两种用户 cannot open directory .: Permission denied 问题 2.Linux权限管理 1).是什么 2).为什么&#xff08;权限角色目标权限属性&#xff09; 3).文件访问者的分类&#xff08;角色&#xff09; 4).文…

大语言模型的压缩技术

尽管人们对越来越大的语言模型一直很感兴趣&#xff0c;但MistralAI 向我们表明&#xff0c;规模只是相对而言的&#xff0c;而对边缘计算日益增长的兴趣促使我们使用小型语言获得不错的结果。压缩技术提供了一种替代方法。在本文中&#xff0c;我将解释这些技术&#xff0c;并…

Java高频面试之集合-14

hello啊&#xff0c;各位观众姥爷们&#xff01;&#xff01;&#xff01;本baby今天来报道了&#xff01;哈哈哈哈哈嗝&#x1f436; 面试官&#xff1a;为什么 HashMap 的容量是 2 的倍数呢&#xff1f; HashMap的容量被设计为2的幂次&#xff0c;主要基于以下原因&#xff…

TreelabPLMSCM数字化供应链解决方案0608(61页PPT)(文末有下载方式)

详细资料请看本解读文章的最后内容。 资料解读&#xff1a;TreelabPLMSCM 数字化供应链解决方案 0608 在当今快速变化的市场环境中&#xff0c;企业面临着诸多挑战&#xff0c;Treelab 数智化 PLM_SCM 行业解决方案应运而生。该方案聚焦市场趋势与行业现状&#xff0c;致力于解…

Docker搭建MySQL主从服务器

一、在主机上创建MySQL配置文件——my.cnf master服务器配置文件路径&#xff1a;/data/docker/containers/mysql-cluster-master/conf.d/my.cnf slave服务器配置文件路径&#xff1a; /data/docker/containers/mysql-cluster-master/conf.d/my.cnf master服务配置文件内容 …

JS逆向案例-HIKVISION-视频监控的前端密码加密分析

免责声明 本文仅为技术研究与渗透测试思路分享,旨在帮助安全从业人员更好地理解相关技术原理和防御措施。任何个人或组织不得利用本文内容从事非法活动或攻击他人系统。 如果任何人因违反法律法规或不当使用本文内容而导致任何法律后果,本文作者概不负责。 请务必遵守法律…

SENT接口

文章目录 前言SENT接口简介物理层数据链路层编码方式帧结构消息格式短串行消息格式增强型串行消息格式 CRC校验和CRC4CRC6 错误检测机制 IP 设计结构框图接口设计上板验证 前言 本文参考标准《SAE J2716_201604》。 SENT接口 简介 SENT&#xff08;Single Edge Nibble Tran…

Qt-搭建开发环境

1.环境搭建 开发工具概述&#xff1a; Qt ⽀持多种开发⼯具&#xff0c;其中⽐较常⽤的开发⼯具有&#xff1a;Qt Creator、Visual Studio、Eclipse. 1.1Qt Creator Qt Creator 是⼀个轻量级的跨平台集成开发环境&#xff08;IDE&#xff09;&#xff0c;专为使⽤ Qt 框架进…

Odoo18 Http鉴权+调用后端接口

最近在调研Odoo18&#xff0c;包括它的前后端原理、源码等。发现官方的开发文档并不十分实用&#xff0c;比如标题这种简单的实用需求&#xff0c;竟然浪费了一点时间&#xff0c;特此记录。 官方文档&#xff1a;External API — Odoo 18.0 documentation 前提&#xff1a;首…

【第13节】windows sdk编程:GDI编程

目录 一、GDI 概述 二、设备环境概念 三、使用 GDI 绘图对象 四、使用 GDI 坐标系统 五、使用GDI绘图 5.1 输出文字 5.2 画点和线 5.3 画矩形框、圆和多边形 5.4 画位图和图标 5.5 双缓冲技术 六、综合代码示例 一、GDI 概述 Windows 应用程序不支持标准输出函数&am…

离开页面取消请求

前言 上一篇文章我们处理了axios的重复请求问题axios重复请求&#xff0c;今天来说一下如何在离开某个页面的时候将正在发送的请求取消掉 开始 基于上一篇的axios封装&#xff0c;当我们在编写某个页面的请求的时候 import request from /request/index;export const test2…

C++输入输出流第一弹:标准输入输出流 详解(带测试代码)

目录 C输入输出流 流的四种状态&#xff08;重点&#xff09; 标准输入输出流 标准输入流 逗号表达式 1. 逗号表达式的基本规则 示例 2. 图片中的代码分析 关键点解析 3. 常见误区 误区 1&#xff1a;逗号表达式等同于逻辑与 && 误区 2&#xff1a;忽略输入…

Z 轴热膨胀系数:PCB 可靠性的关键因素与选材策略

在电子设备小型化与高性能化的趋势下&#xff0c;PCB&#xff08;印刷电路板&#xff09;的可靠性成为决定产品寿命的核心因素。其中&#xff0c;Z 轴热膨胀系数&#xff08;α2/z-CTE&#xff09;作为板材的关键参数&#xff0c;直接影响多层板的层间结合力、焊点稳定性及整体…

【C++】Virtual function and Polymorphism

《C程序设计基础教程》——刘厚泉&#xff0c;李政伟&#xff0c;二零一三年九月版&#xff0c;学习笔记 文章目录 1、多态性的概念2、虚函数的定义2.1、引入虚函数的原因2.2、虚函数的定义与使用2.3、虚函数的限制 3、抽象类3.1、纯虚函数3.2、抽象类 4、应用实例 更多有趣的代…

图解LLM智能体(LLM Agents):构建与运作机制的全面解析

LLM智能体:构建与运作机制 LLM智能体(LLM Agents)正在迅速普及,似乎逐渐取代了我们熟悉的传统对话式LLM。这些令人惊叹的能力并非凭空而来,而是需要多个组件协同工作。 本文包含超过60张定制插图,将深入探讨LLM智能体的领域、其核心组件以及多智能体框架的工作原理。 文…

自动驾驶背后的数学:特征提取中的线性变换与非线性激活

在上一篇博客「自动驾驶背后的数学&#xff1a;从传感器数据到控制指令的函数嵌套」—— 揭秘人工智能中的线性函数、ReLU 与复合函数中&#xff0c;我们初步探讨了自动驾驶技术中从传感器数据到控制指令的函数嵌套流程&#xff0c;其中提到了特征提取模块对传感器数据进行线性…

W80x使用WM IoT SDK 2.X 开发(二)驱动tft屏幕

一、硬件准备 开发板依然是官方送的w803&#xff0c;屏幕我的是2.4寸的ST7789 二、查看sdk 1、例程 tft的有这4个程序&#xff0c;我这里直接看最简单的polling吧 首先就是创建一个任务&#xff0c;这跟上一篇点亮led创建任务的步骤一样 继续点进去 2、spi初始化 先看初始…