经过Vue3的洗礼,最近初始React18,还是觉得有必要对比一下两者进行通信的方式。 主要以 '父子通信','兄弟通信','跨域通信'进行展开
文章有点长,可以收藏起来,慢慢看~~ 但是不要让这篇文章吃灰·哦·
01| 父子组件通信
React18
1.父传子
- 1.父传递数据 子组件标签上添加属性
- 2.子组件接收数据 props 对象接收,包含父组件传递过来的所有属性
react
function App() {
return (
<div>
<Son1 name="李四" age={20} />
</div>
);
}
function Son1(props) {
return (
<div>
<h2>姓名:{props.name}</h2>
<h2>年龄:{props.age}</h2>
<h2>内容:{props.children}</h2>
</div>
);
}
这里props.children
,因为页面有显示props从父组件传递的内容,就为空
但是props.children
是一个很重要react里面重要概念。这里插入简单讲一下
props.children 允许你在组件中嵌套和传递子组件的内容。
children
是一个特殊的prop
,它包含了组件标签内的所有子节点,无论是文本、元素还是其他组件。当你在父组件中使用子组件时,如果没有显式传递某些内容,
props.children
会自动接收子组件标签内的内容。
react
function Parent() {
return (
<Child>
<h1>第一个子节点</h1>
<h2>第二个子节点</h2>
</Child>
);
}
function Child(props) {
return (
<div>
<h2>我是子组件</h2>
<div>
{props.children ? props.children : <p>没有传递内容</p>}
</div>
</div>
);
}
2.子传父
- 1.父组件定义函数,子组件调用函数
- 2.子组件传递函数给父组件
- 3.父组件调用函数
react
import React, { useState } from 'react';
function Parent() {
const [msg, setMsg] = useState('');
const getMsg = (msg) => {
setMsg(msg);
};
return (
<div>
<h2>父组件状态:{msg}</h2>
<Son1 getMsg={getMsg} />
</div>
);
}
function Son1({ getMsg }) {
const sonMsg = '我是Son1子组件';
return <button onClick={() => getMsg(sonMsg)}>点击传递消息</button>;
}
Vue3
1. 父传子
在 Vue 3 中,父组件通过 props
向子组件传递数据,子组件通过 defineProps
来声明接收的 props
。
vue
<template>
<!-- 使用'v-bind:name'将父组件中的parentName变量的值动态绑定到子组件的 `name` 属性上-->
<Son :name="parentName" :age="parentAge" />
</template>
<script setup>
import { ref } from 'vue';
import Son from './Son.vue';
const parentName = ref('李四');
const parentAge = ref(20);
</script>
vue
<!-- Son.vue -->
<template>
<div>
<h2>姓名:{{ name }}</h2>
<h2>年龄:{{ age }}</h2>
</div>
</template>
<script setup>
// 子组件 defineProps 进行接收
defineProps({
name: String,
age: Number
});
</script>
2. 子传父
在 Vue 3 中,子组件通过 $emit
向父组件发送事件,父组件通过 v-on
监听该事件。
vue
<!-- Parent.vue -->
<template>
<!-- @ v-on 简写,使用 v-on 监听子组件的 sendMessage 事件 -->
<Son @sendMessage="receiveMessage" />
<p>{{ message }}</p>
</template>
<script setup>
import { ref } from 'vue';
import Son from './Son.vue';
const message = ref('');
function receiveMessage(msg) {
message.value = msg;
}
</script>
vue
<!-- Son.vue -->
<template>
<button @click="sendMessage">点击传递消息</button>
</template>
<script setup>
const emit = defineEmits();
function sendMessage() {
// 触发 'sendMessage' 事件,并传递消息作为参数
emit('sendMessage', '我是Son组件');
}
</script>
上面defineEmits()
不用声明事件,可以传递任何事件,但同时也失去了对事件的类型检查和编译时验证。多项目中,未知事件传递带来风险。下面采用对象和数组两种方式简单说明,defineEmits()可以进行的检查和编译
数组形式示例
xml
<template>
<button @click="sendMessage">发送消息</button>
<button @click="updateData">更新数据</button>
<button @click="closeModal">关闭模态框</button>
</template>
<script setup>
// 明确声明可以发射的事件
const emit = defineEmits(['sendMessage', 'updateData', 'closeModal']);
function sendMessage() {
emit('sendMessage', '我是Son组件');
}
function updateData() {
emit('updateData', 123, { key: 'value' });
}
function closeModal() {
emit('closeModal');
}
</script>
对象形式示例(TypeScript)
vue
<script setup lang="ts">
interface Emit {
(e: 'sendMessage', message: string): void;
(e: 'updateData', id: number, data: object): void;
(e: 'closeModal'): void;
}
// 明确声明可以发射的事件,并提供类型检查
const emit = defineEmits<Emit>();
</script>
02| 兄弟组件通信
React
兄弟组件的通信通过将共享的状态提升 到父组件来实现。父组件将该状态和修改状态的函数通过 props
传递给子组件。
react
import React, { useState } from 'react';
function Parent() {
const [msg, setMsg] = useState('');
const getMsg = (msg) => {
setMsg(msg);
};
return (
<div>
<h2>父组件状态:{msg}</h2>
<Son1 getMsg={getMsg} />
<Son2 msg={msg} />
</div>
);
}
function Son1({ getMsg }) {
const sonMsg = '我是Son1子组件';
return <button onClick={() => getMsg(sonMsg)}>传递消息</button>;
}
function Son2({ msg }) {
return <h2>兄弟组件接收到的消息:{msg}</h2>;
}
Vue
在 Vue 3 中,兄弟组件的通信也通过将共享的状态提升到父组件来实现。父组件通过 props
向子组件传递数据,子组件通过 emit
向父组件传递事件。
vue
<!-- Parent.vue -->
<template>
<Son1 @sendMessage="receiveMessage" />
<Son2 :msg="message" />
</template>
<script setup>
import { ref } from 'vue';
import Son1 from './Son1.vue';
import Son2 from './Son2.vue';
const message = ref('');
function receiveMessage(msg) {
message.value = msg;
}
</script>
xml
<!-- Son1.vue -->
<template>
<button @click="sendMessage">传递消息</button>
</template>
<script setup>
const emit = defineEmits();
function sendMessage() {
emit('sendMessage', '我是Son1子组件');
}
</script>
xml
<!-- Son2.vue -->
<template>
<h2>兄弟组件接收到的消息:{{ msg }}</h2>
</template>
<script setup>
defineProps({
msg: String
});
</script>
03| 跨层组件通信:使用 context
VS provide
实现
跨层通信由父App组件传给A里面的B组件
React
在 React 中,跨层组件通信可以通过 Context API 来实现。Context
允许你在组件树中传递数据,而不必手动通过每一层的 props
。这种机制对于需要跨越多层嵌套的组件来说非常有用。
- 1.createContext 创建 context 对象,上下文ctx 对象将包含你希望在组件树中共享的数据。
- 2.Provider 提供器,包裹需要跨层通信的组件。将数据通过
value
属性传递给Provider
,任何位于Provider
内部的组件都可以访问到这些数据。 - 3.
useContext
钩子来访问上下文中的数据。useContext
接受一个上下文对象(就是通过createContext
创建的那个对象)作为参数,并返回该上下文的当前值。
js
import React, { createContext, useContext } from 'react';
// 1. 创建 context 对象
const MsgContext = createContext();
function ContextApp() {
const msg = 'this is app';
return (
<>
{/* 2. 使用 Provider 包裹组件并提供数据 */}
<MsgContext.Provider value={msg}>
<div>
<h2>我是 App 组件</h2>
<A />
</div>
</MsgContext.Provider>
</>
);
}
function A() {
const sonMsg = '我是 son1 子组件';
return (
<>
{sonMsg}
<B />
</>
);
}
function B() {
// 3. 使用 useContext 钩子接收数据
const msg = useContext(MsgContext);
return (
<>
<div>this is B,{msg}</div>
</>
);
}
export default ContextApp;
Vue 3
在 Vue 3 中,跨层组件通信可以通过 provide
和 inject
API 来实现。provide
用于提供数据,而 inject
用于在后代组件中获取这些数据。这是 Vue 中实现跨层组件通信的标准方法。
js
<!-- Parent.vue -->
<template>
<div>
<h2>我是 App 组件</h2>
<A />
</div>
</template>
<script setup>
import { provide } from 'vue';
import A from './A.vue';
const msg = 'this is app';
// 1. 使用 provide 提供数据
provide('msg', msg);
</script>
js
<!-- A.vue -->
<template>
<div>
我是 son1 子组件
<B />
</div>
</template>
<script setup>
import B from './B.vue';
</script>
js
<!-- B.vue -->
<template>
<div>
this is B,{{ msg }}
</div>
</template>
<script setup>
import { inject } from 'vue';
// 2. 使用 inject 获取数据
const msg = inject('msg');
</script>
对比:React 与 Vue 的跨层通信
特性 | React | Vue 3 |
---|---|---|
跨层通信方式 | context 和 useContext |
provide 和 inject |
数据传递方向 | Provider 向下传递数据, Consumer 获取数据 |
provide 在父组件提供数据, inject 在后代组件获取数据 |
适用场景 | 适用于中等规模应用,尤其是需要共享全局状态时 | 适用于需要跨越多个层级传递数据的场景 |
总结
React18和Vue3 机制都是为了简化,Vue3哲学注重业务开发,所以通过很多对应的语法。比如,props接收参数,'v-bind'等。React18 适合大型项目,在管理项目和JavaScript运用上面都有深入。 就以跨层组件通信来说,通过 Context (React)或 provide
/inject
(Vue 3) API,开发者可以更加方便地进行跨层组件通信,尤其是当数据需要在深层嵌套的组件间共享时,能极大简化组件的结构和数据流动。
**我相信看到这里的小伙伴中肯定会出现绝世高手~**🚀 🚀
希望这篇文章对大家有帮助,欢迎评论区探讨学习,学会的话也还请给本文一个点赞支持哦~