Vue 3 第十一章:组件二(组件通信)

news/2024/12/12 6:09:15/

文章目录

    • 1. 组件的通信
      • 1.1. 父子组件之间的通信
        • 1.1.1 父组件向子组件传值
        • 1.1.2. 子组件向父组件传值
      • 1.2. 兄弟组件之间的通信
        • 1.2.1. 安装
        • 1.2.2. 注册
        • 1.2.3. 使用
      • 1.3. 跨级组件之间的通信
        • 1.3.1 provide/inject
      • 1.4. 非父子组件之间的通信
        • 1.4.1. Vuex/Pinia
    • 总结

1. 组件的通信

1.1. 父子组件之间的通信

1.1.1 父组件向子组件传值

方式一:父组件给子组件传值时,通过v-on绑定属性实现

// parent.vue
<template><div>父子组件传值<children :msg="msg" :foo="foo"/></div>
</template><script setup lang="ts">
import { ref } from 'vue';
import children from './components/children.vue';let msg = ref('hello word');
let foo = ref(10);
</script><style scoped></style>

子组件通过defineProps来接收接收父组件传递的值。

  • 使用字符串的形式接收父组件传递的值
// children.vue
<template><div class="wrapper">这是子组件<br/>父传子:{{ props.msg }} {{ props.foo }}</div>
</template><script setup lang="ts">
let props = defineProps(['msg', 'foo'])
</script><style scoped></style>
  • 使用对象的形式接收父组件传递的值
// children.vue
<template><div class="wrapper">这是子组件<br/>父传子:{{ props.msg }} {{ props.foo }}</div>
</template><script setup lang="ts">
let props = defineProps({msg: String,foo: Number
})
</script><style scoped></style>
  • 使用对象的形式接收父组件传递的值(含默认值及必填参数设置)
// children.vue
<template><div class="wrapper">这是子组件<br/>父传子:{{ props.msg }} {{ props.foo }}</div>
</template><script setup lang="ts">
let props = defineProps({msg: {type: String,default: '',required: true // 设置后参数必传},foo: {type: Number,default: 0}
})
</script><style scoped></style>
  • 结合 TypeScript 使用
// children.vue
<template><div class="wrapper">这是子组件<br/>父传子:{{ props.msg }} {{ props.foo }}</div>
</template><script setup lang="ts">
let props = defineProps<{msg?: string;foo: number
}>()
</script><style scoped></style>

方式二:父组件通过插槽(slot)向子组件传递参数

  • 子组件中通过slot标签传递参数
  • 父组件中通过template插入内容,通过v-slot可以接收插槽传递的数据
<!-- Parent.vue -->
<template><Child><template #default="{ message }">{{ message }}</template></Child>
</template><script>
import Child from './Child.vue'
</script><!-- Child.vue -->
<template><div><slot :message="message"></slot></div>
</template><script setup lang="ts">
import { ref } from 'vue'
const message = ref('Hello, world!')
</script>

需要注意的是,插槽只能用于传递静态内容,如果需要传递动态内容,则需要使用props或者provide/inject来实现。此外,插槽还可以定义多个,并且可以通过name属性来区分不同的插槽。

方式三:v-model,子组件可直接修改父组件传递过来的值

在Vue3中,可以使用v-model指令来实现子组件直接修改父组件传递过来的值。具体来说,可以在父组件中使用v-model指令将一个变量与子组件的一个prop绑定起来,然后在子组件中使用emit方法触发一个名为update:加上prop名字的事件,并传递一个新的值作为参数。例如:

<!-- VmodelParent.vue -->
<template><div>v-model传参:父组件<VmodelChild v-model:isShow="isShow" /></div>
</template><script setup lang="ts">
import { ref } from 'vue';
import VmodelChild from './components/VmodelChild.vue';const isShow = ref(false)</script><style scoped></style><!-- VmodelChild.vue -->
<template><div>v-model传参:子组件<button @click="handleClick">点击修改参数</button><br />{{ props.isShow }}</div>
</template><script setup lang="ts">
import { defineProps, defineEmits } from 'vue';const props = defineProps({isShow: {type: Boolean,default: false}
})
const emit = defineEmits(["update:isShow"])
const handleClick = () => {emit("update:isShow", !props.isShow)
}</script><style scoped></style>

1.1.2. 子组件向父组件传值

子组件向父组件传值,通过defineEmits实现

<template><div class="wrapper">这是子组件<br/><button @click="emitToParent">click</button></div>
</template><script setup lang="ts">
let emit = defineEmits(['event-to-parent'])
let emitToParent = () => {emit('event-to-parent', '子组件传递给父组件的值')
}</script><style scoped></style>

1.2. 兄弟组件之间的通信

Vue 3 中移除了 eventBus,但可以借助第三方工具来完成。Vue 官方推荐使用mitt tiny-emitter

例子:以mitt为例

1.2.1. 安装

yarn add mitt -S

1.2.2. 注册

  • eventBus.ts
// eventBus.ts
import mitt from 'mitt'const mitter = mitt();export default mitter

1.2.3. 使用

  • EventBus.vue
// EventBus.vue
<template><div>Event Bus实现兄弟组件传参<EventBusA /><EventBusB /></div>
</template><script setup lang="ts">
import EventBusA from './components/EventBusA.vue';
import EventBusB from './components/EventBusB.vue';
</script><style scoped></style>
  • EventBusA.vue
// EventBusA.vue
<template><div class="wrapper">兄弟组件A<button type="button" @click="handleClick">点击传参</button></div>
</template><script setup lang="ts">
import { ref } from 'vue';
import mitter from '@/utils/eventBus'const msg = ref('Hello, world!')const handleClick = () => {mitter.emit('msg', msg.value)
}</script><style scoped></style>
  • EventBusB.vue
// EventBusB.vue
<template><div class="wrapper">兄弟组件B{{ res }}</div>
</template><script setup lang="ts">
import mitter from '@/utils/eventBus'
import { ref } from 'vue'const res = ref()mitter.on('msg', (data) => {res.value = data
})
</script><style scoped></style>

1.3. 跨级组件之间的通信

provide/inject来实现跨级组件之间的通信

1.3.1 provide/inject

  • parent.vue
// parent.vue
<template><div class="wrapper">兄弟组件传参,这是父组件<brotherA /><brotherB /></div>
</template><script setup lang="ts">
import brotherA from './components/brotherA.vue'
import brotherB from './components/brotherB.vue'
import { provide, ref } from 'vue';let msg = ref('给孙组件传递的值');
provide('msg', msg)</script><style scoped></style>
  • brotherA.vue
// brotherA.vue
<template><div class="wrapper">子组件A<grandson /></div>
</template><script setup lang="ts">
import grandson from "./grandson.vue";
import { ref } from 'vue';</script><style scoped></style>
  • brotherB.vue
// brotherB.vue
<template><div class="wrapper">子组件B{{ msg }}</div>
</template><script setup lang="ts">
import { inject } from 'vue'let msg = inject('msg')
</script><style scoped></style>
  • grandson.vue
// grandson.vue
<template><div class="wrapper">这是孙组件{{ msg }}</div>
</template><script setup lang="ts">
import { inject } from 'vue'let msg = inject('msg')
</script><style scoped></style>

1.4. 非父子组件之间的通信

1.4.1. Vuex/Pinia

Vuex 和 Pinia 是 Vue 3 中的状态管理工具,使用这两个工具可以轻松实现组件通信。由于这两个工具都比较强大,后面会写文章详细讲解。

总结

组件通信是 Vue 中非常重要的一个概念,它指的是组件之间传递数据和事件的过程。在 Vue 中,组件通信主要分为父子组件之间的通信和兄弟组件之间的通信两种情况。
在父子组件之间的通信中,父组件可以通过v-bind来向子组件传递数据,而子组件则可以通过defineProps来接收父组件传递的数据。同时,子组件也可以通过emit触发自定义事件来向父组件传递数据。
在兄弟组件之间的通信中,可以通过一个共同的父组件来实现数据的传递和事件的触发,也可以通过 Vuex 等状态管理工具来实现数据的共享。
总之,在组件通信的过程中,需要合理地选择合适的方法来实现数据和事件的传递,以实现组件之间的良好协作和高效交互。


http://www.ppmy.cn/news/45447.html

相关文章

软考 软件设计师上午题面向对象

面向过程和面向对象 省略面向对象可以省略过程&#xff0c;复杂事情简单化 类 类是对象的抽象&#xff0c;对象是类的实例 一般类是交通工具。特殊类是轮船飞机。因为他们是特殊的佳通工具&#xff0c;一个天上的一个海上的 对象 属性别名状态成员变量&#xff0c;方法也叫…

轻松掌握微服务治理的注册中心Eureka到Nacos知识点

1、SpringCloud 1、介绍 2、消费者与服务者 3、服务拆分 1、介绍 2、服务之间调用 例如有两个微服务&#xff0c;分别提供用户信息和订单信息。两个服务都有自己的数据库&#xff0c;所以如下查订单信息是不能直接去查用户信息的数据库的&#xff0c;只能从订单服务发起远程…

L2-030 冰岛人

2018年世界杯&#xff0c;冰岛队因1:1平了强大的阿根廷队而一战成名。好事者发现冰岛人的名字后面似乎都有个“松”&#xff08;son&#xff09;&#xff0c;于是有网友科普如下&#xff1a; 冰岛人沿用的是维京人古老的父系姓制&#xff0c;孩子的姓等于父亲的名加后缀&#x…

“科技助力财富增值 京华四季伴您一生”,北银理财深化线下线上客户交流互动

2023年4月12日&#xff0c;北银理财有限责任公司&#xff08;以下简称“北银理财”&#xff09;携手东方财富网启动北银理财财富号&#xff0c;首次采用线上直播及线下主题演讲相结合的方式&#xff0c;在上海举办以“科技助力财富增值&#xff0c;京华四季伴您一生”为主题的机…

华科超算用户手册的学习笔记

1. 资源计费 1.1 费用记账 日期费用&#xff08;上限3000元&#xff09;2023.04.171002023.04.18200总计300 1.2 创建实例时显示项目的余额不足 这是因为项目账户之中目前还没有足够的卡时&#xff1b; Note 这里是因为上次充值的卡时还在田老师的个人账户中&#xff0c;还需…

code=45, title=禁止登录, message=登录失败,建议升级最新版本后重试,或通过问题反馈与我们联系。

如果你是采用 java 开发的&#xff0c;你可以参考本文章&#xff0c;java 和 kotlin 都是可以相互转换的。 在解决之前&#xff0c;先说明环境: JDK版本&#xff1a;java version "17.0.3.1" 【Oracle JDK】 Kotlin版本&#xff1a;1.8.20 采取simbot核心包开发&am…

单片机的实例——28BYJ48步进电机

整体过程 准备资料1&#xff0c;步进电机内部结构示意图2&#xff0c;步进电机命名3&#xff0c;实际结构的转速比4&#xff0c;数值的含义5&#xff0c;实际内部主动轮结构分析实际内部机构及接线定子部分转子部分 定子和转子磁极的工作分析 6&#xff0c;工作时序7&#xff0…

JVM之GC日志解读

通过阅读Gc日志&#xff0c;我们可以了解Java虚拟机内存分配与回收策略。 内存分配与垃圾回收的参数列表 -XX:PrintGC 输出GC日志。类似&#xff1a;-verbose:gc -XX:PrintGCDetails 输出GC的详细日志 -XX:PrintGCTimestamps 输出GC的时间戳&#xff08;以基准时间的形式&#…