当前位置: 首页 > news >正文

【总结】Vue中的组件通信方式有哪些?React中的组件通信方式有哪些?

文章目录

      • 一.Vue中的组件通信
        • 1.父传子
        • 2.子传父
        • 3.事件总线EventBus
        • 4.ref和$Refs
        • 5.Vuex
      • 二.React中的组件通信
        • 1.父传子
        • 2.子传父
        • 3.状态提升(兄弟组件通信)
        • 4.跨层级(祖孙组件通信)

一.Vue中的组件通信

1.父传子

思路:父组件在子组件占位符上绑定自定义属性,子组件通过props接收传值
示例:

//父组件:ProductDetail.vue 
data(){return:{count:0}
}
//把value作为自定义属性值
<CountBox :value="count" />//子组件:CountBox.vue 
//接收父组件的自定义属性value
props:{value:{type:Number}
}
//调用value数据,让input框有默认值
<input type="text :value="value"/>
2.子传父

思路:子组件使用$emit,第一个参数绑定自定义事件名,第二个参数传值给父组件,父组件在使用自定义事件接收传值
示例:

//父组件:ProductDetail.vue 
//父组件把input作为自定义事件,并用count接收传值,更新count的值
<CountBox :value="count" @input="count" />//子组件:CountBox.vue 
methods:{handleAdd(){//子组件把input作为自定义事件名,把value+1作为新值传给父组件this.$emit('input',this.value+1)},handleInput(e){this.$emit('input',e.target.value)}
}
<button @click="handleAdd">+</button>
<input type="text :value="value" @click="handleInput" />
<button @click="handleSub">-</button>

知识点:
v-model是语法糖,它等价于@input事件和value属性,上例中父组件可优化为:

<CountBox :value="count" @input="count" />
简写为:
<CountBox v-model='count' />

其他场景中v-model的拆解如下:

  • input文本框中,它是由value属性和oninput事件构成的
  • 多选框中,它是由checked属性和onchange事件构成的
  • select下拉菜单中,它是由value属性和onchange事件构成的
3.事件总线EventBus

思路:
创建一个事件总线并导出,并在组件中导入,一个组件使用$emit发送数据,另一组件使用$on接收数据,最后可以使用$off移除eventBus

示例:

//step1:创建事件总线utils/EventBus.js
import Vue from "vue"
const Bus=new Vue();//通过一个空的Vue实例作为中央事件总线(事件中心)
export default Bus;//step2:在组件A引入事件总线并调用$emit发送数据
<button @click="handleClick">点击</button>
......
import Bus from "@/utils/EventBus.js";data() {return {num:100};},methods: {handleClick() {console.log("发送数据了...");Bus.$emit("changeNum", this.num);},},//step3:在组件B引入事件总线并使用$on接收数据
<div>{{count}}</div>
......
import Bus from "@/utils/EventBus.js";data() {return {count:0};},mounted() {Bus.$on("changeNum", (num) => {console.log("接收到数据了...",num);this.count += num;});}

注意事项和优化:

1).不能在模板中直接调用Bus.$emit,写成:<button @click="Bus.$emit("changeNum", this.num)">点击</button>
2).注销事件总线beforeDestroy() {// 清理事件监听,避免内存泄漏Bus.$off('custom-event', this.handleEvent);}
3).可以在main.js注册全局的Bus,而不用在每个组件中引入并注册import { Bus } from '@/utils/event-bus';Vue.prototype.$bus = Bus;  // 全局注入
4.ref和$Refs

思路:父组件在子组件占位符上绑定ref属性.并在事件中通过$ref来调用子组件中对外暴露的方法
示例:

//子组件:ArticleDetail.vue
{{message}}
......data() {return {message: ''};},methods: {// 对父组件暴露的方法getMsg(newMsg){console.log('我是子组件的方法,获取的数据是:', newMsg);  this.message = newMsg;}}//父组件:Article.vue
<div><ArticleDetail ref="ChildRef" /><button @click="sendToChild">点击</button>
</div>
......
import ArticleDetail from './ArticleDetail.vue'
export default {components: {ArticleDetail,},methods:{sendToChild() {this.$refs.ChildRef.getMsg(this.msg);  // 调用子组件的方法}},data: () => ({msg:"hello Ref!",})}
//结果:父组件点击触发事件,子组件模板渲染{{message}}
5.Vuex

思路:把数据存在仓库的state中,不同组件分别调用mutations中更改state数据的方法
示例:

//step1:创建仓库store/index.js
import Vue  from "vue";
import Vuex from "vuex";Vue.use(Vuex);export default new Vuex.Store({state: {isVaild: true},mutations: {setVaild(state, isVaild) {state.isVaild = isVaild;}},actions: {}
});//step2:在main.js中全局注入
import store from "./store/index.js"
new Vue({store,render: h => h(App),
})//step3:在组件中调用
<div class="wrapper"><button @click="handleClick">点击</button><div v-if="isVaild"> 显示了</div>
</div>
......computed: {...mapState(['isVaild'])},methods: {handleClick() {this.$store.commit('setVaild', false)}},
//结果:点击按钮触发事件,更改isVaild的值,隐藏div标签

二.React中的组件通信

1.父传子

格式同Vue,略
示例一:

function Son(props){return <div>我是子组件,接收到的数据是:{props.info}</div>
}
function App(){return {<div><Son info={message666}></Son></div>}
}
//输出:我是子组件,接收到的数据是:message666

示例二.

//父组件Parent.js
import React, { useState } from 'react';
import Child from './Child'; // 导入单独文件的子组件
const Parent = () => {const [msg,setMsg] = useState("hello react!");return (<div><div>{/* 向子组件传递数据:自定义属性为msg */}<Child msg={msg} /><button onClick={()=>{setMsg("hi react!")}}>点击切换</button></div></div>);
};
export default Parent;//子组件Child.js
import React from 'react';
// 子组件通过props接收父组件传递的数据
const Child = ({msg}) => {return (<div><p>子组件接收到的数据: {msg}</p></div>);
};
export default Child;
2.子传父

步骤:

  • 1.父组件定义一个回调函数,用于接收子组件传递的值
  • 2.父组件把该回调函数作为props传给子组件
  • 3.子组件在点击事件中调用该回调函数并传参

示例:

//父组件Parent.js
import React, { useState } from 'react';
import Child from './Child'; // 导入单独文件的子组件
const Parent = () => {const [msg,setMsg] = useState("hello react!");//子传父step1:父组件定义一个回调函数,用于接收子组件传递的数据const getMsg = (msg) => {console.log('子组件传递的数据: ',msg)}return (<div><div>{/* 子传父step2:父组件将这个回调函数作为props传递给子组件*/}<Child msg={msg} onGetSonMsg={getMsg} /><button onClick={()=>{setMsg("hi react!")}}>点击切换</button></div></div>);
};
export default Parent;//子组件:Child.js
import React from 'react';
const Child = ({onGetSonMsg}) => {const msg1='你好'return (<div>{/* 子传父step3:子组件在点击事件中调用父组件传递的回调函数,并传递数据 */}<button onClick={()=>{onGetSonMsg(msg1)}}>点击传递数据给父组件</button></div>);
};
export default Child;
3.状态提升(兄弟组件通信)

(状态提升:我的理解是都把状态提升到共同的父组件App.js中,类似于vue中的EventBusvuex)
思路:
将共享状态提升到最近的共同父组件中,然后通过props传递给子组件,同时将修改状态的函数也传递给子组件,这样兄弟组件就可以通过父组件来同步状态。
(流程:Son1子传父给父组件App,父组件App再父传子下发给Son2)
(难点:父组件获取到子组件Son1的数据后,要用变量接收,且要在将来的父传子中传给Son2并动态显示,解决方法是把数据做成状态再下发)
示例:

//第三步--子传父step3:在点击事件中调用回调函数并传参
const msg1="hello React!!"
function Son1(onGetSonMsg){//子组件1return <button onClick={onGetSonMsg(msg1)}>点击</button>
}
//第六步--父传子step2:通过props属性接收父组件传值
function Son2(props){return <div>接收兄弟组件的数据为:{props.msgToSon2}<
function App(){const [msg,setMsg]=useState('')//第一步--子传父step1:准备回调函数const getMsg=message=>{//console.log("接收子组件传递数据:",message)setMsg(message)//第四步--状态提升到父组件:把子传父获取到的数据作为状态变量msg的最新值}return{{*第二步-子传父step2:把回调函数作为props值传给子组件*}<Son1 onGetSonMsg={getMsg}/>{*第五步--父传子step1:把状态变量msg作为自定义属性的值传给Son2*}<Son2 msgToSon2={msg}/>}
}
4.跨层级(祖孙组件通信)

步骤:

  • 1.使用createContext方法创建一个上下文对象Ctx
  • 2.在顶层组件(App)中通过Ctx.Provider为组件提供数据
  • 3.在底层组件(Grandson)中通过钩子函数useContext获取数据

示例:

//App.js
import { React,useState, createContext, useContext } from 'react';
const msg='hello'//准备App==>Grandson的数据
// step1:使用createContext方法创建一个上下文对象Ctx
const Ctx=createContext("默认消息")
return ({/* step2:在顶层组件(App)中通过Ctx.Provider为组件提供数据 */}<Ctx.Provider value={msg}><div style={{padding: '20px', border: '1px solid #ccc'}}><h2>App组件(数据提供方)</h2><Son /></div></Ctx.Provider>
)
// 中间组件
function Son(){return (<div style={{margin: '15px', padding: '15px', border: '1px dashed #999'}}><h3>Son组件(中间层)</h3><Grandson /></div>)
}
// 底层组件
function Grandson(){// step3:在底层组件(Grandson)中通过钩子函数useContext获取数据const message=useContext(Ctx)console.log(message)return (<div style={{margin: '10px', padding: '10px', background: '#f0f0f0'}}><h4>Grandson组件(数据消费方)</h4><p>接收到的消息:<strong>{message}</strong></p></div>)
}
http://www.dtcms.com/a/524751.html

相关文章:

  • 外贸网站优化推广手工制作大全折纸
  • 华为一站式服务建站视觉设计案例
  • 前端大文件分片上传
  • webrtc代码走读(四)-QOS-NACK实现-发送端
  • 主成分分析(PCA)在计算机图形学中的深入解析与应用
  • Kubernetes:实战Pod共享存储
  • 合肥市建设工程造价管理站网站ps网站背景图片怎么做
  • 5118网站是免费的吗网站如何防止重登录
  • 网络编程实战02·从零搭建Epoll服务器
  • IP数据报分片 题
  • 杭州设计 公司 网站建设适合小企业的erp软件
  • 全面掌握PostgreSQL关系型数据库,创建用户创建数据库操作,笔记09
  • 西安市网站制作公司购物商城排名
  • 思维大反转——往内走如实觉察
  • 计算机视觉——从环境配置到跨线计数的完整实现基于 YOLOv12 与质心追踪器的实时人员监控系统
  • 《商户查询缓存案例》使用案例学习Redis的缓存使用;缓存击穿、穿透、雪崩的原理的解决方式
  • 物联网固件安全更新中的动态密钥绑定与验证机制
  • YOLO学习——图像分割入门 “数据集制作和模型训练”
  • 网站域名的用处如何建设黔货出山电子商务网站
  • 三步搭建 AI 客服系统:用 PandaWiki 打造永不掉线的智能客服
  • 现在做一个网站多少钱网站制作商城
  • 详解EMQX2-EMQX功能使用
  • Vue3 中使用 CesiumJS
  • 【Trae+AI】Express框架01:教程示例搭建及基础原理
  • C# 中的 `as` 关键字:安全类型转换
  • Java 14 新特性Record、instanceof、switch语法速览
  • 网站的空间域名做公司网站的南宁公司
  • 中英文网站建站太原网站建设招聘
  • 建一个网站大概需要多长时间2016网站开发语言
  • 在Windows上使用Selenium + Chrome Profile实现自动登录爬虫