Vue2和Vue3 组件通信,方式有哪些,都有什么区别?
咱们来聊聊 Vue2 和 Vue3 里组件通信的事儿,组件通信就像是不同部门之间传递消息,让各个组件能协同工作。下面分别说说它们的通信方式以及区别。
Vue2 组件通信方式
1. 父传子:props
这就像是领导给下属分配任务。父组件通过 props
把数据传递给子组件。父组件在使用子组件的标签上,用自定义属性来传递数据,子组件在 props
选项里声明要接收哪些数据。
例子:
<!-- 父组件 -->
<template><ChildComponent :message="parentMessage" />
</template><script>
import ChildComponent from './ChildComponent.vue';
export default {components: {ChildComponent},data() {return {parentMessage: '这是来自父组件的消息'};}
};
</script><!-- 子组件 -->
<template><p>{{ message }}</p>
</template><script>
export default {props: ['message']
};
</script>
2. 子传父:$emit
这好比下属向领导汇报工作。子组件通过 $emit
触发一个自定义事件,父组件监听这个事件,当事件触发时,子组件可以把数据传递给父组件。
例子:
<!-- 子组件 -->
<template><button @click="sendMessage">发送消息给父组件</button>
</template><script>
export default {methods: {sendMessage() {this.$emit('childEvent', '这是来自子组件的消息');}}
};
</script><!-- 父组件 -->
<template><ChildComponent @childEvent="handleChildEvent" />
</template><script>
import ChildComponent from './ChildComponent.vue';
export default {components: {ChildComponent},methods: {handleChildEvent(message) {console.log(message);}}
};
</script>
3. 非父子组件通信:事件总线(Event Bus)
这就像公司里有个公共的消息板,大家都可以在上面发消息和看消息。创建一个事件总线对象,组件可以通过它来触发事件和监听事件,从而实现非父子组件之间的通信。
例子:
// event-bus.js
import Vue from 'vue';
export const eventBus = new Vue();// 发送消息的组件
import { eventBus } from './event-bus.js';
export default {methods: {sendMessage() {eventBus.$emit('messageEvent', '这是一条广播消息');}}
};// 接收消息的组件
import { eventBus } from './event-bus.js';
export default {created() {eventBus.$on('messageEvent', (message) => {console.log(message);});}
};
4. Vuex
这就像是公司有个大的资料室,所有组件都可以去那里拿资料和放资料。Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
Vue3 组件通信方式
1. 父传子:props
和 Vue2 类似,还是领导给下属分配任务。只不过在 Vue3 的组合式 API 里,接收 props
的方式有变化。
例子:
<!-- 父组件 -->
<template><ChildComponent :message="parentMessage" />
</template><script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
const parentMessage = ref('这是来自父组件的消息');
</script><!-- 子组件 -->
<template><p>{{ message }}</p>
</template><script setup>
import { defineProps } from 'vue';
const props = defineProps({message: String
});
</script>
2. 子传父:defineEmits
也是下属向领导汇报工作,不过在 Vue3 里用 defineEmits
来定义可以触发的事件。
例子:
<!-- 子组件 -->
<template><button @click="sendMessage">发送消息给父组件</button>
</template><script setup>
import { defineEmits } from 'vue';
const emit = defineEmits(['childEvent']);
const sendMessage = () => {emit('childEvent', '这是来自子组件的消息');
};
</script><!-- 父组件 -->
<template><ChildComponent @childEvent="handleChildEvent" />
</template><script setup>
import ChildComponent from './ChildComponent.vue';
const handleChildEvent = (message) => {console.log(message);
};
</script>
3. 非父子组件通信:provide/inject
这就像公司里有个资源共享库,上级组件提供资源,下级组件可以注入使用,不管隔了多少层。
例子:
<!-- 上级组件 -->
<template><ChildComponent />
</template><script setup>
import { provide, ref } from 'vue';
const sharedData = ref('这是共享的数据');
provide('sharedData', sharedData);
</script><!-- 下级组件 -->
<template><p>{{ sharedData }}</p>
</template><script setup>
import { inject } from 'vue';
const sharedData = inject('sharedData');
</script>
4. Vuex 或 Pinia
Vuex 还是那个大资料室,而 Pinia 是 Vue3 推荐的新状态管理库,功能和 Vuex 类似,但使用起来更简单。
区别
语法差异
Vue3 引入了组合式 API,像 defineProps
、defineEmits
这些新的语法来处理 props
和自定义事件,和 Vue2 的选项式 API 写法不同。
非父子组件通信方式侧重点
Vue2 常用事件总线,但是当项目变大时,事件总线管理起来会比较混乱。Vue3 更推荐使用 provide/inject
,它的层级关系更清晰,而且能更好地和组合式 API 配合使用。
状态管理库
Vue3 除了可以继续用 Vuex,还推荐使用 Pinia,Pinia 更符合现代 JavaScript 的特性,代码更简洁,使用起来也更方便。