最全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') // 修改状态
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值