Vue组件间通信的9种实现方式

组件的通信

父子组件通信

父子组件通信可以理解成:
父组件向子组件传值。
父组件调用子组件的方法。

子组件向父组件传值。
子组件调用父组件的方法。

1.props: 利用props属性实现父组件向子组件传值。

parent.vue文件


<template><div>父组件<!-- 子组件在不同的父组件中传递 --><children data="我是父组件传递的值" ></children><children data="我是父组件传递的值" :num="18"></children></div>
</template>
<script setup lang="ts">
import children from '@/components/children.vue'
</script>

children.vue 文件

<template><div>子组件:{{data}}<div>年龄: {{num}}</div></div>
</template>
<script lang="ts">
import { defineComponent } from "vue";export default defineComponent({name: 'children',props: {data: String,num: {type: Number,default: () => 20},}
})
</script>

props不仅可以传字符串、数字、数组、对象、boolean的值,在传递时props也可以定义数据校验,以此来限制接收的数据类型等。
父传子的方式形成了一个单向下行绑定,叫做单向数据流。父级props的更新也会向下流程到接收这个props的子组件中,触发对应的更新,但是反过来则不行。如果遇到确实需要改变props值的应用场合,则采用下面的解决方法:

children.vue文件

<template><div><div>必须被修改的值第一种:  {{myData}}</div><div>必须被修改的值第二种:  {{childData}}</div></div>
</template>
<script lang="ts">
import { computed, defineComponent, ref } from "vue";export default defineComponent({name: 'children',props: {data: String,num: {type: Number,default: () => 20},},setup(props) {// 第一种const myData = ref(props.data)myData.value = '通过初始化的方式进行修改'// 第二种const childData = computed(() => {return props.data + '通过computed属性实现修改'})return {myData,childData}}
})
</script>

2. $refs: 利用$refs属性可以实现父组件调用子组件的方法。通常用于直接操作子组件,但不推荐用于数据传递。

Vue2的写法

    <refChild ref="childRef"></refChild>this.$refs.refChild?.childFn()

Vue3的写法
parent.vue文件

<template><div class="mt15">  $refs通信的子组件<refChild ref="compontentRef"></refChild></div>
</template>
<script lang="ts">
import refChild from '@/components/refChild.vue'
import { defineComponent, onMounted, ref } from 'vue'export default defineComponent({name: 'parent',components: {refChild},setup() {const compontentRef = ref(null)const getRefChild = () => {compontentRef.value?.childFn();}onMounted(() => {getRefChild();})return {compontentRef,getRefChild}}
})

refChild.vue文件

<template><div>$refs紫组件</div>
</template>
<script lang="ts">
import { defineComponent } from "vue";export default defineComponent({name: 'refChild',setup(props, context) {const childFn = () => {console.log('fn的方法被调用')}// 第一种写法context.expose({ childFn: childFn })// 第二种写法 defineExpose不需要引入,直接使用// defineExpose({ childFn: childFn })}
})
</script>

3.slot: 通过插槽实现父组件向子组件传值。关于插槽

// 父组件<div><slotChild>默认传值的方式</slotChild></div>
// 子组件
<template><div><slot></slot></div>
</template>

4.$emit: 触发当前组件实例上的事件,可以理解成子组件触发了绑定在父组件上的自定义事件。

parent.vue文件

 <children data="我是父组件传递的值" :num="18" @fromGreet="fromGreet"></children>
import { defineComponent, onMounted, ref } from 'vue'
import children from '@/components/children.vue'
import refChild from '@/components/refChild.vue'
import slotChild from '@/components/slotChild.vue'export default defineComponent({name: 'parent',components: {children,},setup() {const fromGreet = (data) => {console.log('来自子组件的调用', data)}return {fromGreet}}
})

children.vue文件

<template><div>子组件:{{data}} <a-button type="primary" @click="greet">打招呼</a-button></div>
</template>
import { computed, defineComponent, ref } from "vue";export default defineComponent({name: 'children',props: {data: String,},setup(props, context) {const greet = () => {context.emit('fromGreet', 'hello')}return {greet}}
})

5.$parent: 在子组件直接获取父组件的实例,从而调用父组件中的方法,类似于$refs获取子组件的方法。

因Vue3的组合式API设计原则,应该尽量避免直接使用$parent,可能会导致组件之间的耦合度过高。推荐下面的实现方法:

parent.vue文件

    <children @call-parent-method="toChildClick"></children>
    const toChildClick = (data) => {console.log('来自子组件的调用', data)}

children.vue文件

  <a-button danger @click="getParentFn">调用父组件的方法</a-button>
import { computed, defineComponent, ref } from "vue";export default defineComponent({name: 'children',emits: ['call-parent-method'],setup(props, context) {const getParentFn = () => {context.emit('call-parent-method');}return {getParentFn}}
})

Vue2的写法可参考$refs。

6. 事件总线EventBus/mitt实现兄弟组件通信

在Vue2中,可以采用EventBus这种方法。利用一个空的Vue实例来作为桥梁,实现事件分发,它的工作原理是发布/订阅方法,通常称为Pub/Sub,也就是发布和订阅的模式。

var bus = new Vue()// 组件A
bus.$emit('event', 'hello from component A')// 组件B
bus.$on('event', (message) => {console.log(message); // 'hello from component A'
}) 

在Vue3中,采用第三方事件总线库mitt取代了EventBus事件。mitt的使用方法和EventBus非常类似,同样是基于Pub/Sub模式,并且更加简单,可以在需要进行通信的地方直接使用。

首先需要安装:

npm install mitt

创建一个工具包 eventBus.ts

import mitt from 'mitt';
export const emitter = mitt();

在componentA组件

<a-button type="primary" @click="sendMessage">发送消息给兄弟组件</a-button>
import { emitter } from '@/utils/eventBus'
export default defineComponent({setup(props, context) {const sendMessage = () => {// 发布一个事件emitter.emit('sendMessage', 'hello from component A')}return {sendMessage}}
})

在componetB组件

<div>message from component A: {{ message }}
</div>
import { defineComponent, onMounted, onUnmounted, ref } from "vue";
import { emitter } from '@/utils/eventBus'export default defineComponent({setup(props, context) {const message = ref('')onMounted(() => {emitter.on('sendMessage', (msg) => {message.value = msg;})})onUnmounted(() => {emitter.off('sendMessage')})return {message}}
})

事件总线的方式进行通信使用起来非常简单,可以实现任意组件之间的通信,其中没有多余的业务逻辑,只需要在状态变化组件触发一个事件,随后在处理逻辑组件监听该事件即可。

7. provide/inject AP实现跨级组件

provide/inject是一种跨组件传递数据的方式,允许祖先组件向其所有子孙后代注入依赖,而不必一层层地通过props传递。

import { defineComponent, provide, ref } from 'vue'
export default defineComponent({setup(props, context) {const theme = ref('dark')provide('theme', theme)}
})
<div>主题: {{ theme }}
</div>
import { defineComponent, ref, inject } from "vue";export default defineComponent({setup(props, context) {const theme = inject('theme')return {theme}}
})

8.vuex状态管理

对于一些大型的项目,要实现复杂的组件通信和状态管理。
组合式API的写法

import { createStore } from 'vuex'export default createStore({state: {message: 'vue'},mutations: {UPDATE_MESSAGE(state, newMessage) {state.message = newMessage},},actions: {updateMessage({ commit }, message) {commit('UPDATE_MESSAGE', message)},},getters: {message: state => state.message;}
})// 在组件中获取信息
const store = useStore()const message = computed(() => store.getters.message)const updateMessage = () => {store.dispatch('updateMessage','New Message')
}

9.pinia状态管理

Pinia主打简单和轻量,其大小仅有1KB。
组合式API写法

import { ref, computed } from 'vue'
import { defineStore } from 'pinia'export const useCounterStore = defineStore('counter', () => {const count = ref(0)const doubleCount = computed(() => count.value * 2)const increment = () => {count.value++}return { count, doubleCount, increment }
})// 在文件中引入
import { useCounterStore } from '@/stores/counter'export default defineComponent({setup() {const counter = useCounterStore()counter.count++;// 两种写法// 第一种counter.$patch({ count: counter.count + 1})// 第二种counter.increment();}
})

前3种解释了父组件向子组件传值的不同写法,4,5解释了子组件向父组件传值及调用方法。6解释了兄弟组件之间的通信,7解释了不同组件之间通信,8,9状态管理适合用于大型应用,组件众多,状态零散地分布在需要组件和组件之间的交互操作中,复杂度也不断增长的项目。

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

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

相关文章

jmeter脚本-请求体设置变量and请求体太长的处理

目录 1、查询接口 1.1 准备组织列表的TXT文件&#xff0c;如下&#xff1a; 1.2 添加 CSV数据文件设置 &#xff0c;如下&#xff1a; 1.3 接口请求体设置变量&#xff0c;如下&#xff1a; 2、创建接口 2.1 见1.1 2.2 见1.2 2.3 准备创建接口的请求体TXT文件&#xff…

SQL,力扣题目1549,每件商品的最新订单【窗口函数】

一、力扣链接 LeetCode_1549 二、题目描述 表: Customers ------------------------ | Column Name | Type | ------------------------ | customer_id | int | | name | varchar | ------------------------ customer_id 是该表主键. 该表包含消费者的…

卸载 Adobe Genuine Software Client

一、问题描述 使用破jie版Adobe Acrobat Pro DC软件后&#xff0c;会经常弹出以下窗口&#xff1a; 且上述探窗无法直接关掉。即使通过任务管理器将其临时关掉&#xff0c;可等过一段时间后&#xff0c;仍然会再次弹出&#xff0c;严重干扰工作进度。 二、问题解决 &#xff…

京东云雅典娜刷机步骤(需要拆机)

京东云雅典娜刷机步骤 必须拆机 必须拆机 必须拆机 刷机要用的文件 1.高通驱动文件&#xff08;USB刷机必备&#xff09;&#xff1a;https://pan.quark.cn/s/6405674f981b 2.进入临时uboot的程序&#xff1a;https://pan.quark.cn/s/ebc1d449cb89 3.uboot固件&#xff1a; ht…

电子商城购物平台的设计与开发+ssm(lw+演示+源码+运行)

摘 要 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;电子商城购物平台小程序被用户普遍使用&#xff0c;为方便…

基于 Spring Boot 和 Vue 的门票销售创新系统

作者介绍&#xff1a;✌️大厂全栈码农|毕设实战开发&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 &#x1f345;获取源码联系方式请查看文末&#x1f345; 推荐订阅精彩专栏 &#x1f447;&#x1f3fb; 避免错过下次更新 Springboot项目精选实战案例 更多项目…

【Python】Python自习课:第一个python程序

【Python】Python自习课&#xff1a;第一个python程序 示例

docker-compose安装rabbitmq 并开启延迟队列和管理面板插件(rabbitmq_delayed_message_exchange)

问题&#xff1a; 解决rabbitmq-plugins enable rabbitmq_delayed_message_exchange &#xff1a;plugins_not_found 我是在docker-compose环境部署的 services:rabbitmq:image: rabbitmq:4.0-managementrestart: alwayscontainer_name: rabbitmqports:- 5672:5672- 15672:156…

103 - Lecture 2 Table and Data Part 1

SQL - Tables and Data Part 1 Relational Database Management System(RDBMS) 关系型数据库管理系统&#xff08;RDBMS&#xff09;是基于关系模型的数据库系统&#xff0c;它支持多种关系操作。关系模型是一种数据存储和检索的模型&#xff0c;它使用表格来组织数据&#x…

PropTypes 和 TypeScript 在 React 中的比较

文章目录 引言PropTypes什么是 PropTypes&#xff1f;如何使用 PropTypes优点缺点 TypeScript什么是 TypeScript&#xff1f;如何使用 TypeScript优点缺点 选择建议总结 引言 在 React 开发中&#xff0c;组件的可复用性和可维护性至关重要。为了确保组件接收到正确的 props&a…

【自动化利器】12个评估大语言模型(LLM)质量的自动化框架

LLM评估是指在人工智能系统中评估和改进语言和语言模型的过程。在人工智能领域&#xff0c;特别是在自然语言处理&#xff08;NLP&#xff09;及相关领域&#xff0c;LLM评估具有至高无上的地位。通过评估语言生成和理解模型&#xff0c;LLM评估有助于细化人工智能驱动的语言相…

儿童安全座椅行业全面深入分析

儿童安全座椅就是一种专为不同体重&#xff08;或年龄段&#xff09;的儿童设计&#xff0c;将孩子束缚在安全座椅内&#xff0c;能有效提高儿童乘车安全的座椅。欧洲强制性执行标准ECE R44/03的定义是&#xff1a;能够固定到机动车辆上&#xff0c;带有ISOFIX接口、LATCH接口的…

Pytest-Bdd-Playwright 系列教程(6):在测试步骤函数中设置别名数据共享

Pytest-Bdd-Playwright 系列教程&#xff08;6&#xff09;&#xff1a;在测试步骤函数中设置别名&数据共享 前言一、步骤别名二、特性文件三、测试脚本四、运行测试五、小测验总结 前言 有的时候&#xff0c;为了提高可读性&#xff0c;我们需要使用不同的名称来声明相同的…

【笔记】变压器-热损耗-频响曲线推导 - 03 变压器参数-特性

参考《Mn-Zn开关电源用铁氧体磁心 PQ系列》&#xff0c;March 2014版 1.可能选择的型号和参数 PQ系列的这种铁氧体结构设计是TDK首创的。 优势是&#xff0c;相对E, EER磁芯&#xff0c;安装面积更小材质选择 PC47PC90PC95尺寸 PQ20/16 最小PQ50/50 最大 2.特性 2.1 温升与…

Unity性能优化 -- 性能分析工具

Stats窗口Profiler窗口Memory Profiler其他性能分析工具&#xff08;Physica Debugger 窗口&#xff0c;Import Activity 窗口&#xff0c;Code Coverage 窗口&#xff0c;Profile Analyzer 窗口&#xff0c;IMGUI Debugger 窗口&#xff09; Stats 统级数据窗口 game窗口 可…

一些swift问题

写得比较快&#xff0c;如果有问题请私信。 序列化和反序列化 反序列化的jsonString2只是给定的任意json字符串 private func p_testDecodeTable() {let arr ["recordID123456", "recordID2"]// 序列化[string] -> json datalet jsonData try? JSO…

VMware虚拟机Debian扩展磁盘

一、 版本 VMware&#xff1a;Workstation 17 Pro虚拟机&#xff1a;Debian11 二、 VMware虚拟机扩展 虚拟机关机状态快照或者备份&#xff1a;以免扩容失败导致文件丢失虚拟机——设置——硬盘——磁盘使用工具——扩展——扩展磁盘容量——设置为想要的大小 三、 虚拟机…

GameFramework教程☀️福利(五):关于该框架的一些意义

文章目录 📢 不同模式的意义本章探讨GF这样编写的意义和使用场景。 📢 不同模式的意义 最近在做一个app,现在在调研阶段。 代码上后期可能用华佗进行C#热更新。 在调研华佗打包完的热更代码如何和UI AB结合起来时,看到了: "> 从这一点可以延伸理解出,当我们使…

【漏洞复现】某平台-QRcodeBuildAction-LoginSSO-delay-mssql-sql注入漏洞

《Java代码审计》http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247484219&idx1&sn73564e316a4c9794019f15dd6b3ba9f6&chksmc0e47a67f793f371e9f6a4fbc06e7929cb1480b7320fae34c32563307df3a28aca49d1a4addd&scene21#wechat_redirect 《Web安全》h…