vue2组件通信
vue2组件通信方式
-
父子组件通信
- 父传子(
props):父组件通过props向子组件传递数据 - 子传父(
$emit):子组件通过事件触发向父组件传递数据【自定义事件】 - 父访问子(
$refs):父组件通过ref直接访问子组件实例 - 子访问父(
$parent):子访问父子组件通过$parent访问父组件实例 - 父访问子(
$children):父访问子组件通过$children访问子组件实例 - 父子通信(
solt):默认插槽(父->子组件传递一段 HTML 结构)、具名插槽(传递多个不同结构,子组件按名称接收)、作用域插槽(子->父组件传递数据(核心:子传父结构 + 数据))
- 父传子(
-
跨级组件通信
$attrs / $listeners:用于隔代组件传递数据和事件provide / inject:用于深层组件间数据传递(非响应式,适合传递配置信息)PubSub(发布 - 订阅模式)【非vue内置】
-
兄弟组件通信
- 通过共同父组件中转:利用父组件作为中间层传递数据
- 事件总线(Event Bus):创建全局事件中心实现任意组件通信
-
大型应用状态管理
- Vuex:专为 Vue 设计的状态管理模式,适合复杂应用
props
父传子(props):父组件通过props向子组件传递数据
// 父组件
<child-component :message="parentMsg"></child-component>
// 子组件
export default {
props: ['message'], // 或详细定义类型 { type: String, required: true }
mounted() {
console.log(this.message)
}
}
$emit
子传父($emit):子组件通过事件触发向父组件传递数据
// 子组件
export default {
methods: {
handleClick() {
this.$emit('child-event', '数据') // 触发事件并传递数据
}
}
}
// 父组件
<child-component @child-event="handleChildEvent"></child-component>
methods: {
handleChildEvent(data) {
console.log(data) // 接收子组件数据
}
}
$refs
父访问子($refs):父组件通过ref直接访问子组件实例
// 父组件
<child-component ref="childRef"></child-component>
mounted() {
console.log(this.$refs.childRef) // 访问子组件实例
this.$refs.childRef.childMethod() // 调用子组件方法
}
$parent
$children
子访问父($parent):子访问父子组件通过$parent访问父组件实例
// 子组件
mounted() {
console.log(this.$parent) // 访问父组件实例
console.log(this.$parent.parentData) // 访问父组件数据
}
插槽
默认插槽:父组件向子组件传递一段 HTML 结构
<!-- 子组件 Child.vue -->
<div class="container">
<slot></slot> <!-- 插槽出口 -->
</div>
<!-- 父组件 -->
<Child>
<p>这是父组件传递的内容</p> <!-- 插槽内容 -->
</Child>
具名插槽:传递多个不同结构,子组件按名称接收
<!-- 子组件 -->
<div>
<slot name="header"></slot>
<slot name="content"></slot>
</div>
<!-- 父组件 -->
<Child>
<template v-slot:header>
<h1>标题</h1>
</template>
<template v-slot:content>
<p>内容</p>
</template>
</Child>
作用域插槽:子组件向父组件传递数据(核心:子传父结构 + 数据)
<!-- 子组件 -->
<div>
<!-- 子组件将数据通过slot-scope传递给父组件 -->
<slot :user="user" :age="18"></slot>
</div>
export default {
data() {
return { user: { name: '张三' } }
}
}
<!-- 父组件 -->
<Child>
<!-- 父组件接收子组件传递的数据并渲染 -->
<template v-slot="slotProps">
<p>{{ slotProps.user.name }} - {{ slotProps.age }}</p>
</template>
</Child>
$attrs / $listeners
- $attrs / $listeners:用于隔代组件传递数据和事件
- $attrs:包含父组件传递的非 props 属性(不包含 class 和 style)
- $listeners:包含父组件传递的所有事件监听器
// 父组件
<parent-component :msg="msg" @parent-event="handleEvent"></parent-component>
// 中间组件
<child-component v-bind="$attrs" v-on="$listeners"></child-component>
// 孙组件
export default {
mounted() {
console.log(this.$attrs.msg) // 获取祖父组件数据
this.$emit('parent-event', '数据') // 触发祖父组件事件
}
}
provide / inject
provide / inject:用于深层组件间数据传递(非响应式,适合传递配置信息)
// 祖先组件
export default {
provide() {
return {
theme: 'dark' // 提供数据
}
}
}
// 后代组件
export default {
inject: ['theme'], // 注入数据
mounted() {
console.log(this.theme) // 使用数据
}
}
PubSub
PubSub 不是 Vue 内置的,而是一种通用的设计模式,常用于跨组件通信(尤其是非父子关系)。在 Vue 项目中,通常会使用pubsub-js这个库实现
- 使用步骤
- 安装:npm install pubsub-js --save
- 引入:import PubSub from ‘pubsub-js’
- 核心 API
- 发布事件:PubSub.publish(‘事件名’, 数据)
- 订阅事件:PubSub.subscribe(‘事件名’, (msg, data) => { … })(返回一个订阅 ID)
- 取消订阅:PubSub.unsubscribe(订阅ID)
// 组件A(发布者)
import PubSub from 'pubsub-js'
methods: {
sendData() {
PubSub.publish('user-updated', { name: '张三' })
}
}
// 组件B(订阅者)
import PubSub from 'pubsub-js'
mounted() {
this.pubId = PubSub.subscribe('user-updated', (msg, data) => {
console.log('收到数据:', data) // msg是事件名,data是传递的数据
})
},
beforeDestroy() {
PubSub.unsubscribe(this.pubId) // 组件销毁时取消订阅,防止内存泄漏
}
与 Event Bus 的区别
- Event Bus 基于 Vue 实例的事件系统,而 PubSub 是独立的库,不依赖 Vue
- 功能上类似,但 PubSub 提供了更丰富的 API(如按事件名取消所有订阅)
- 在 Vue 项目中,Event Bus 更轻量,而 PubSub 适合更复杂的跨框架场景
通过共同父组件中转
通过共同父组件中转:利用父组件作为中间层传递数据
// 兄组件 -> 父组件 -> 弟组件
// 兄组件
this.$emit('brother-data', data)
// 父组件
<brother1 @brother-data="handleData"></brother1>
<brother2 :data="sharedData"></brother2>
// 弟组件
props: ['data']
事件总线(Event Bus)
事件总线(Event Bus):创建全局事件中心实现任意组件通信
// main.js 中创建事件总线
Vue.prototype.$bus = new Vue()
// 发送方组件
this.$bus.$emit('event-name', data)
// 接收方组件
mounted() {
this.$bus.$on('event-name', (data) => {
console.log(data)
})
},
beforeDestroy() {
this.$bus.$off('event-name') // 移除事件监听,防止内存泄漏
}
Vuex
Vuex:专为 Vue 设计的状态管理模式,适合复杂应用
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
}
},
actions: {},
modules: {}
})
// 组件中使用
this.$store.state.count // 获取状态
this.$store.commit('increment') // 修改状态

1053

被折叠的 条评论
为什么被折叠?



