【Vue3】组件通信

Vue3组件通信和Vue2的区别:

  • 移出事件总线,使用mitt代替。
  • vuex换成了pinia
  • .sync优化到了v-model里面了。
  • $listeners所有的东西,合并到$attrs中了。
  • $children被砍掉了。

在这里插入图片描述

1. props

  • 父传子:属性值是非函数
  • 子传父:属性值是函数

父组件:

<template><div class="father"><h3>--父组件,</h3><h4>我的车:{{ car }}</h4><h4>儿子给的玩具:{{ toy }}</h4><Son:car="car":getSonToy="getSonToy"/></div>
</template><script setup lang="ts">
import Son from './Son.vue'
import { ref } from "vue";
// 数据
const car = ref('奔驰')
const toy = ref()
// 方法
function getSonToy(value: string) {toy.value = value
}
</script>

子组件:

<template><div class="child"><h3>--子组件--</h3><h4>我的玩具:{{ toy }}</h4><h4>父给我的车:{{ car }}</h4><button @click="getSonToy(toy)">玩具给父亲</button></div>
</template><script setup lang="ts">
import { ref } from "vue";
const toy = ref('奥特曼')defineProps(['car', 'getSonToy'])
</script>

在这里插入图片描述

2. 自定义事件

常用于:子 => 父

原生事件:

  • 事件名是特定的(clickmosueenter等等)
  • 事件对象$event: 是包含事件相关信息的对象(pageXpageYtargetkeyCode

自定义事件:

  • 事件名是任意名称
  • 事件对象$event: 是调用emit时所提供的数据,可以是任意类型

父组件:

<template><div class="father"><h3>--父组件,</h3><h4>我的车:{{ car }}</h4><h4>儿子给的玩具:{{ toy }}</h4><Son@get-son-toy="getSonToy"/></div>
</template><script setup lang="ts">
import Son from './Son.vue'
import { ref } from "vue";
// 数据
const car = ref('奔驰')
const toy = ref()
// 方法
function getSonToy(value: string) {toy.value = value
}
</script>

子组件:

<template><div class="child"><h3>--子组件--</h3><h4>我的玩具:{{ toy }}</h4><!-- <h4>父给我的车:{{ car }}</h4> --><button @click="emit('get-son-toy', toy)">玩具给父亲</button></div>
</template><script setup lang="ts">
import { ref } from "vue";
const toy = ref('奥特曼')const emit = defineEmits(['get-son-to:y'])
</script>

在这里插入图片描述

扩展一个知识点:$event

<template><div class="child"><h3>--子组件--</h3><h4>我的玩具:{{ toy }}</h4><!-- <h4>父给我的车:{{ car }}</h4> --><!-- <button @click="emit('get-son-toy', toy)">玩具给父亲</button> --><button @click="test('1', $event)">test</button></div>
</template><script setup lang="ts">
import { ref } from "vue";
const toy = ref('奥特曼')// const emit = defineEmits(['get-son-toy'])
const test = (a: string, e: Event) => {console.log(a, e);
}
</script>

image.png

$event 为事件对象。

3. mitt

任意组件之间通信。

emitter.ts

// 引入mitt 
import mitt from "mitt";// 创建emitter
const emitter = mitt()/*// 绑定事件emitter.on('abc',(value)=>{console.log('abc事件被触发',value)})emitter.on('xyz',(value)=>{console.log('xyz事件被触发',value)})setInterval(() => {// 触发事件emitter.emit('abc',666)emitter.emit('xyz',777)}, 1000);setTimeout(() => {// 清理事件emitter.all.clear()}, 3000); 
*/// 创建并暴露mitt
export default emitter

子组件:

<template><div class="child"><h3>--子组件--</h3><h4>我的玩具:{{ toy }}</h4><button @click="emitter.emit('send-toy', toy)">玩具给父亲</button></div>
</template><script setup lang="ts">
import { ref } from "vue";
import emitter from '../utils/emitter'
const toy = ref('奥特曼')</script>

父组件:

<template><div class="father"><h3>--父组件,</h3><h4>我的车:{{ car }}</h4><h4>儿子给的玩具:{{ toy }}</h4><Son/></div>
</template><script setup lang="ts">
import Son from './Son.vue'
import { ref, onUnmounted } from "vue";
import emitter from '../utils/emitter'// 数据
const car = ref('奔驰')
const toy = ref()
// 绑定事件
emitter.on('send-toy', (data) => {toy.value = dataconsole.log('send-toy事件被触发', data)
})onUnmounted(() => {// 解绑事件emitter.off('send-toy')
})
</script>

image.png

4. v-model

组件库底层父子传参常用。

MyInput 组件:

<template><div class="box"><inputtype="text":value="modelValue"@input="emit('update:modelValue', (<HTMLInputElement>$event.target).value)"></div>
</template><script setup lang="ts">
// 接收props
defineProps(['modelValue'])
// 声明事件
const emit = defineEmits(['update:modelValue'])
</script>

父组件:

<template><div class="father"><h3>--父组件--</h3><MyInput v-model="username"/><!-- 原理: --><!-- <MyInput :modelValue="username" @update:modelValue="username = $event"/> --></div>
</template><script setup lang="ts">
import MyInput from './MyInput.vue'
import {ref} from 'vue'
const username = ref('name')
</script>

image.png

  • 对于原生事件, $event就是事件对象=====>能使用.target
  • 对于自定义事件,$event就是触发事件时,所传递的数据==>不能.target

此外,还可以进行部分自定义修改:

父组件:

<MyInput v-model:myname="username"/>

MyInput 组件:

<template><div class="box"><inputtype="text":value="myname"@input="emit('update:myname', (<HTMLInputElement>$event.target).value)"></div>
</template><script setup lang="ts">
// 接收props
defineProps(['myname'])
// 声明事件
const emit = defineEmits(['update:myname'])
</script>

5. $attrs

用于祖孙传参。

具体说明:$attrs是一个对象,包含所有父组件传入的标签属性。

$attrs会自动排除props中声明的属性

Father.vue

<template><div class="father"><h3>--Father--</h3><div>a: {{ a }}</div><div>b: {{ b }}</div><Son :a="a" :b="b" :addA="addA"  v-bind="{x: 100, y: 200}" ></Son></div>
</template><script setup lang="ts">
import {ref} from 'vue'
import Son from './Son.vue'const a = ref(1)
const b = ref(2)const addA = (data: number)=> {a.value += data
}</script>

Son.vue

<template><div class="box"><h3>--Son--</h3><div>a: {{ a }}</div><GrandSon v-bind="$attrs"/></div>
</template><script setup lang="ts">
import GrandSon from './GrandSon.vue';defineProps(['a'])
</script>

GrandSon.vue

<template><div class="box"><h3>--GrandSon--</h3><div>b: {{ b }}</div><div>x: {{ x }}</div><div>y: {{ y }}</div><button @click="addA(1)">点我将a加1</button></div>
</template><script setup lang="ts">defineProps(['b', 'x', 'y' ,'addA'])
</script>

image.png

image.png

6. $refs$parent

概述:

  • $refs用于 :父→子。
  • $parent用于:子→父。

原理如下:

属性说明
$refs值为对象,包含所有被ref属性标识的DOM元素或组件实例。
$parent值为对象,当前组件的父组件实例对象。

Father.vue

<template><div class="father"><h3>父组件</h3><h4>房产:{{ house }}</h4><button @click="changeToy">修改Child1的玩具</button><button @click="changeComputer">修改Child2的电脑</button><button @click="getAllChild($refs)">让所有孩子的书变多</button><Child1 ref="c1" /><Child2 ref="c2" /></div>
</template><script setup lang="ts" name="Father">
import Child1 from './Child1.vue'
import Child2 from './Child2.vue'
import { ref, reactive } from "vue";
let c1 = ref()
let c2 = ref()// 注意点:当访问obj.c的时候,底层会自动读取value属性,因为c是在obj这个响应式对象中的
// 解释了为什么refs[key].book等写法后面不加.value
/* let obj = reactive({a:1,b:2,c:ref(3)
})
let x = ref(4)console.log(obj.a)
console.log(obj.b)
console.log(obj.c)
console.log(x) */// 数据
let house = ref(4)
// 方法
function changeToy() {c1.value.toy = '小猪佩奇'
}
function changeComputer() {c2.value.computer = '华为'
}
function getAllChild(refs: { [key: string]: any }) {console.log(refs)for (let key in refs) {refs[key].book += 3}
}
// 向外部提供数据
defineExpose({ house })
</script><style scoped>
.father {background-color: rgb(165, 164, 164);padding: 20px;border-radius: 10px;
}.father button {margin-bottom: 10px;margin-left: 10px;
}
</style>

Child1.vue

<template><div class="child1"><h3>子组件1</h3><h4>玩具:{{ toy }}</h4><h4>书籍:{{ book }}</h4><button @click="minusHouse($parent)">干掉父亲的一套房产</button></div>
</template><script setup lang="ts" name="Child1">
import { ref } from "vue";
// 数据
let toy = ref('奥特曼')
let book = ref(3)// 方法
function minusHouse(parent: any) {parent.house -= 1
}// 把数据交给外部
defineExpose({ toy, book })</script><style scoped>
.child1 {margin-top: 20px;background-color: skyblue;padding: 20px;border-radius: 10px;box-shadow: 0 0 10px black;
}
</style>

Child2.vue

<template><div class="child2"><h3>子组件2</h3><h4>电脑:{{ computer }}</h4><h4>书籍:{{ book }}</h4></div>
</template><script setup lang="ts" name="Child2">
import { ref } from "vue";
// 数据
let computer = ref('联想')
let book = ref(6)
// 把数据交给外部
defineExpose({ computer, book })
</script><style scoped>
.child2 {margin-top: 20px;background-color: orange;padding: 20px;border-radius: 10px;box-shadow: 0 0 10px black;
}
</style>

7. provide、inject

实现祖孙组件直接通信。

  • 在祖先组件中通过provide配置向后代组件提供数据
  • 在后代组件中通过inject配置来声明接收数据

Father 组件:

<template><div class="father"><h3>父组件</h3><h4>银子:{{ money }}万元</h4><h4>车子:一辆{{car.brand}}车,价值{{car.price}}万元</h4><Child/></div>
</template><script setup lang="ts" name="Father">import Child from './Child.vue'import {ref,reactive,provide} from 'vue'let money = ref(100)let car = reactive({brand:'奔驰',price:100})function updateMoney(value:number){money.value -= value}// 向后代提供数据provide('moneyContext',{money,updateMoney})provide('car',car)</script><style scoped>.father {background-color: rgb(165, 164, 164);padding: 20px;border-radius: 10px;}
</style>

GrandChild 组件:

<template><div class="grand-child"><h3>我是孙组件</h3><h4>银子:{{ money }}</h4><h4>车子:一辆{{car.brand}}车,价值{{car.price}}万元</h4><button @click="updateMoney(6)">花爷爷的钱</button></div>
</template><script setup lang="ts" name="GrandChild">import { inject } from "vue";let {money,updateMoney} = inject('moneyContext',{money:0,updateMoney:(param:number)=>{}})let car = inject('car',{brand:'未知',price:0})
</script><style scoped>.grand-child{background-color: orange;padding: 20px;border-radius: 10px;box-shadow: 0 0 10px black;}
</style>

8. pinia

【Pinia】快速入门及数据持久化-CSDN博客

9. slot

【Vue3】slot 插槽全家桶_vue 多个匿名slot-CSDN博客

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

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

相关文章

泡泡玛特旗下IP亮相2024米兰时装周 LABUBU等化身时尚观察员​

2024年1月14日&#xff0c;在意大利米兰时装周上&#xff0c;泡泡玛特旗下IP THE MONSTERS成员LABUBU、ZIMOMO惊艳亮相PRONOUNCE珀琅汐2024秋冬大秀现场&#xff0c;作为时尚观察员的LABUBU和ZIMOMO以其独特的潮玩形象打动了顶级时尚圈。 据了解&#xff0c;泡泡玛特和PRONOUNC…

Qt简介及安装

“这不属于我&#xff0c;因为沉默背后也有冲动” 在互联网当中&#xff0c;最关注的几个比较核心的岗位&#xff1a; &#x1f6f6; 后端开发 &#x1f6f6; 前端开发 &#x1f6f6; 算法工程师 &#x1f6f6; 游戏开发 像后端开发中有认识…

VUE+Vis.js鼠标悬浮title提前显示BUG解决方法

在使用VUEVis.js做拓扑图&#xff0c;利用鼠标悬浮放在图标展示设备信息时&#xff0c;发现鼠标一放在图标上面时&#xff0c;标题表会提前在放置的元素下显示&#xff0c;鼠标再放到图标上去元素才会隐藏变成悬浮状态 解决方法&#xff1a; 添加一个div元素&#xff0c;设置v…

linux修改文件夹下所有文件的权限(常用)

1、 修改文件夹下所有文件的权限 # filename为要修改的文件夹名字。-R应该是表示递归修改filename文件夹下所有文件的权限 sudo chmod -R 777 filename2、linux修改单个文件夹权限 sudo chmod 600 &#xff08;只有所有者有读和写的权限&#xff09; sudo chmod 644 &#…

Java 设计者模式以及与Spring关系(七) 命令和迭代器模式

简介: 本文是个系列一次会出两个设计者模式作用&#xff0c;如果有关联就三个&#xff0c;除此外还会讲解在spring中作用。 23设计者模式以及重点模式 我们都知道设计者模式有3类23种设计模式&#xff0c;标红是特别重要的设计者模式建议都会&#xff0c;而且熟读于心&#…

什么是EJB?

什么是EJB&#xff1f; EJB (Enterprise JavaBeans) 是一种用于开发企业级应用程序的 Java 服务器端组件模型。它是一种分布式对象架构&#xff0c;用于构建可移植、可伸缩和可事务处理的企业级应用。 EJB 提供了一种将业务逻辑组件化、模块化的方式&#xff0c;使开发人员能够…

李跳跳派大星v2.2.0软件安装教程(附软件下载地址)

软件简介&#xff1a; 软件【下载地址】获取方式见文末。注&#xff1a;推荐使用&#xff0c;更贴合此安装方法&#xff01; 李跳跳派大星v2.2.0最新安卓版是一款功能强大的Guang告屏蔽软件。它为用户提供了一种快速、便捷的方式来去除各种软件中的开屏Guang告&#xff0c;让…

《WebKit 技术内幕》学习之五(4): HTML解释器和DOM 模型

4 影子&#xff08;Shadow&#xff09;DOM 影子 DOM 是一个新东西&#xff0c;主要解决了一个文档中可能需要大量交互的多个 DOM 树建立和维护各自的功能边界的问题。 4.1 什么是影子 DOM 当开发这样一个用户界面的控件——这个控件可能由一些 HTML 的标签元素…

Spring Security 之摘要认证

摘要认证 注意: 在现代应用程序中不应该使用摘要认证,因为它不被认为是安全的。最明显的问题是你必须以明文或加密或 MD5 格式存储密码。所有这些存储格式都被认为是不安全的。相反,你应该使用单向自适应密码哈希(如 bCrypt、PBKDF2、SCrypt 等)来存储凭据,而这是摘要认…

STL第一讲

一、认识headers、版本、重要资源 1. C Standard Library和Standard Template Library 前者&#xff1a;c标准库&#xff1b;后者直译为“标准模板库” 区别: C标准库&#xff1a;是c编译器提供的自带的头文件(不带.h后缀)新版兼容C的头文件的形式cxxxx&#xff1b;旧版的xxx…

简单Web UI 自动化测试框架 seldom

pyse 更名为 seldom WebUI automation testing framework based on Selenium and unittest. 基于 selenium 和 unittest 的 Web UI自动化测试框架。 特点 提供更加简单API编写自动化测试。提供脚手架&#xff0c;快速生成自动化测试项目。自动生成HTML测试报告生成。自带断言方…

100GB Mellanox InfiniBand 网卡虚拟化技术调研

调研目的 验证 Mellanox InfiniBand 100GB网卡和SR650 Server能兼容 ThinkSystem SR650 Power On (Booting OS or in undetected OS) Machine Type/Model7X05CTO1WW 验证 SR-IOV虚拟话技术在BIOS/Firmware/Kernel/QEMU/Libvirt能被支持 4.18.0-305.19.1.el8_4.x86_64 验证…

Web开发5:第三方扩展与部署

在Web开发中&#xff0c;第三方扩展和部署是提高开发效率和功能扩展的重要手段。第三方扩展可以帮助我们快速集成常用功能和工具&#xff0c;而部署则是将我们的应用程序发布到生产环境中。本文将介绍第三方扩展的重要性、如何选择和使用常见的第三方扩展&#xff0c;并讨论应用…

Java Web(三)--CSS

介绍 为什么需要&#xff1a; 在没有 CSS 之前&#xff0c;想要修改 HTML 元素的样式需要为每个 HTML 元素单独定义样式属性&#xff0c;费心费力&#xff1b;CSS 可以让 html 元素(内容) 样式(CSS)分离&#xff0c;提高web 开发的工作效率(针对前端开发)&#xff0c;从而…

论文翻译:On Bringing Robots Home

On Bringing Robots Home 关于引入机器人到家庭 文章目录 On Bringing Robots Home关于引入机器人到家庭1 Introduction1 引言2 Technical Components and Method2 技术组件与方法2.1 Hardware Design2.1 硬件设计2.2 Pretraining Dataset – Homes of New York2.2 预训练数据…

微信小程序开发创建component组件,报错WXML file not found解决方案

报错如下&#xff1a; 解决方案&#xff1a; 在组件.json文件加上"styleIsolation": "apply-shared",&#xff1a;

C++ 数论相关题目(欧拉函数)

欧拉函数 给定 n 个正整数 ai &#xff0c;请你求出每个数的欧拉函数。 欧拉函数的定义 1∼N 中与 N 互质的数的个数被称为欧拉函数&#xff0c;记为 ϕ(N) 。 若在算数基本定理中&#xff0c;Npa11pa22…pamm &#xff0c;则&#xff1a; ϕ(N) Np1−1p1p2−1p2…pm−1pm 输…

人工智能的未来:机遇与挑战

人工智能的未来:机遇与挑战 0引言 随着科技的飞速发展,人工智能(AI)已经成为了我们生活中不可或缺的一部分。从智能手机、自动驾驶汽车到智能家居系统,人工智能的应用已经深入到各个领域。然而,尽管人工智能为我们带来了诸多便利,但它也引发了一系列关于隐私、安全和道…

Spring Security 之 表单登录

表单登录 Spring Security提供了支持通过HTML表单提供用户名和密码。本节详细介绍了Spring Security中表单身份验证的工作原理。 本节将介绍Spring Security中的基于表单的登录工作原理。首先,我们将看到用户如何被重定向到登录表单。 第1步,用户首先对其未经授权的资源(/…

【Spring】Spring AOP原理

文章目录 前言代理模式静态代理动态代理JDK动态代理CGLib 动态代理 总结 前言 前面我们学习了关于 Spring AOP 的使用&#xff0c;那么今天这篇文章&#xff0c;我们将深入理解 Spring AOP 的原理&#xff0c;也就是 Spring 是如何实现 AOP 的。 Spring AOP 是基于动态代理来…