vue组件间如何实现通信
组件通信方式
在 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>