组件通信方式
在 Vue2 中,有以下几种方式实现组件通信:
-
props/ e m i t :父组件通过 p r o p s 向子组件传递数据,子组件通过 emit:父组件通过props向子组件传递数据,子组件通过 emit:父组件通过props向子组件传递数据,子组件通过emit 事件向父组件发送消息。
-
p a r e n t / parent/ parent/children:通过 p a r e n t 和 parent和 parent和children 访问父组件和子组件的实例。
-
r e f s :通过 refs:通过 refs:通过refs 获取子组件的引用,并直接调用子组件中的方法或属性。
-
eventBus:使用一个独立的 Vue 实例作为事件总线,通过 e m i t 和 emit和 emit和on 触发和监听自定义事件。
-
Vuex:当需要多个组件共享状态时,可以使用 Vuex 来管理全局状态。
在 Vue3 中,由于采用了 Composition API,组件通信变得更加灵活和直观。以下是几种常用的方法:
-
props/context:通过 props 将数据从父组件传递给子组件,在子组件中使用 setup 函数中的 context 对象访问父组件的属性或方法。
-
provide/inject:与 props/context 类似,provide/inject 同样用于父子组件之间的通信,但是它可以让祖先组件向所有后代组件注入数据,而不仅仅是直接后代组件。
-
ref/teleport:通过 ref 获取组件的引用,并使用 teleport 将组件挂载到指定的 DOM 节点上。
-
EventBus/Emitter:与 Vue2 类似,可以使用一个独立的 Vue 实例作为事件总线,在组件之间发送和接收自定义事件。
-
Vuex 4.x: 可以使用 Vuex 来管理全局状态,但是在 Vue3 中有了更好的支持,使用新的 API 替换了旧 API,并且提供了更好的类型安全性和开箱即用的响应式需求。
总体而言,Vue2 和 Vue3 中的组件通信方法大同小异,但是由于 Vue3 采用 Composition API,使得组件通信更加方便和灵活。
vue2 组件通信 demo
以下是其中几种常见的方式及示例代码:
- 父子组件通信:父组件通过 props 向子组件传递数据,子组件通过 $emit 触发事件通知父组件。
父组件:
<template>
<child-component :message="parentMessage" @update-message="updateParentMessage"></child-component>
</template>
<script>
import ChildComponent from './ChildComponent.vue'
export default {
components: {
ChildComponent
},
data() {
return {
parentMessage: ''
}
},
methods: {
updateParentMessage(message) {
this.parentMessage = message
}
}
}
</script>
子组件:
<template>
<div>
{{ message }}
<button @click="onClick">Update Message</button>
</div>
</template>
<script>
export default {
props: {
message: String
},
methods: {
onClick() {
const newMessage = 'New message from child component'
this.$emit('update-message', newMessage)
}
}
}
</script>
- 兄弟组件通信:通过一个空的 Vue 实例作为中央事件总线(event bus),将其作为一个全局的事件管理器来实现兄弟组件之间的通信。
事件总线:
import Vue from 'vue'
export default new Vue()
组件 A:
<template>
<div>
{{ message }}
<button @click="onClick">Update Message</button>
</div>
</template>
<script>
import EventBus from './EventBus'
export default {
data() {
return {
message: ''
}
},
methods: {
onClick() {
const newMessage = 'New message from component A'
EventBus.$emit('update-message', newMessage)
}
},
created() {
EventBus.$on('update-message', (message) => {
this.message = message
})
}
}
</script>
组件 B:
<template>
<div>
{{ message }}
</div>
</template>
<script>
import EventBus from './EventBus'
export default {
data() {
return {
message: ''
}
},
created() {
EventBus.$on('update-message', (message) => {
this.message = message
})
}
}
</script>
- Vuex 状态管理:通过 Vuex 实现全局状态管理,各组件共享同一个状态。
store:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
message: ''
},
mutations: {
updateMessage(state, message) {
state.message = message
}
}
})
组件 A:
<template>
<div>
{{ message }}
<button @click="onClick">Update Message</button>
</div>
</template>
<script>
export default {
computed: {
message() {
return this.$store.state.message
}
},
methods: {
onClick() {
const newMessage = 'New message from component A'
this.$store.commit('updateMessage', newMessage)
}
}
}
</script>
组件 B:
<template>
<div>
{{ message }}
</div>
</template>
<script>
export default {
computed: {
message() {
return this.$store.state.message
}
}
}
</script>
Vue3 组件通信
Vue 3 提供了多种组件通信方式,以下是其中一些常用的示例:
- props 和 emit
父组件通过 props 向子组件传递数据,子组件通过 emit 方法向父组件发送事件。
父组件 template:
<template>
<child-component :message="msg" @send-message="handleMessage"></child-component>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent
},
data() {
return {
msg: 'Hello World'
}
},
methods: {
handleMessage(message) {
console.log(message);
}
}
}
</script>
子组件 template:
<template>
<div>
{{ message }}
<button @click="sendMessage">Send Message</button>
</div>
</template>
<script>
export default {
props: {
message: String
},
methods: {
sendMessage() {
this.$emit('send-message', 'Hi Parent!');
}
}
}
</script>
- provide 和 inject
provide 和 inject 可以在祖先组件提供数据,然后在后代组件中使用。
祖先组件:
<template>
<grand-child-component></grand-child-component>
</template>
<script>
import { provide } from 'vue';
export default {
setup() {
const name = 'John';
provide('name', name);
return {};
}
}
</script>
后代组件:
<template>
<div>{{ name }}</div>
</template>
<script>
import { inject } from 'vue';
export default {
setup() {
const name = inject('name');
return {
name
}
}
}
</script>
- $attrs 和 $listeners
a t t r s 包含了父组件传递给子组件的所有属性, attrs 包含了父组件传递给子组件的所有属性, attrs包含了父组件传递给子组件的所有属性,listeners 包含了父组件在子组件上绑定的所有事件监听器。
子组件:
<template>
<div v-bind="$attrs" v-on="$listeners">{{ message }}</div>
</template>
<script>
export default {
props: {
message: String
},
}
</script>
父组件 template:
<template>
<child-component message="Hello World" class="text-red" @click="handleClick"></child-component>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent
},
methods: {
handleClick() {
console.log('Clicked!');
}
}
}
</script>