Vue组件通信方式详解

一、父子组件通信

1. Props(父→子)

父组件通过props向子组件传递数据,子组件需要显式声明接收的props

dart 复制代码
// 父组件
<ChildComponent :title="pageTitle" :content="pageContent" />

// 子组件
props: {
  title: String,          // 基础类型检查
  content: {             // 高级配置
    type: String,
    required: true,
    default: 'Default content'
  }
}

2. 自定义事件(子→父)

子组件通过$emit触发事件,父组件通过v-on监听

typescript 复制代码
// 子组件
methods: {
  submitForm() {
    this.$emit('form-submit', { 
      username: this.username,
      password: this.password
    })
  }
}

// 父组件
<ChildComponent @form-submit="handleSubmit" />

methods: {
  handleSubmit(formData) {
    // 处理表单数据
  }
}

3. style和class

父组件传递的样式和类会自动合并到子组件根元素

javascript 复制代码
// 父组件
<ChildComponent 
  class="theme-dark" 
  style="margin: 10px; padding: 20px;"
/>

// 子组件渲染结果
<div class="child-component theme-dark" style="margin: 10px; padding: 20px;">
  <!-- 子组件内容 -->
</div>

4. attribute(非Prop特性)

attribute(非Prop特性)是指父组件传递给子组件,但子组件没有在props中显式声明的属性。这些特性会自动绑定到子组件的根元素上。

javascript 复制代码
// 父组件
<ChildComponent data-id="123" aria-label="Description" />

// 子组件(未在props中声明这些属性)
<div data-id="123" aria-label="Description">
  <!-- 子组件内容 -->
</div>
  1. this.$attrs访问 : 在子组件中,可以通过this.$attrs访问所有非Prop特性:

    javascript 复制代码
    mounted() {
      console.log(this.$attrs) // 包含所有未在props中声明的属性
    }
  2. 使用场景

    • 当需要将多个属性批量传递给子组件时
    • 创建高阶组件(HOC)时传递未知属性
    • 需要手动控制属性绑定位置时
  3. 禁用自动继承 : 在子组件选项中设置inheritAttrs: false可以禁用自动绑定到根元素:

    javascript 复制代码
    export default {
      inheritAttrs: false,
      // ...
    }
  4. 手动绑定示例

    javascript 复制代码
    <template>
      <div>
        <input v-bind="$attrs" />
      </div>
    </template>
  5. 包含的特性

    • 普通HTML属性(如id, class, data-*等)
    • 自定义属性(非props声明的)
    • 事件监听器(可通过$listeners单独访问)
javascript 复制代码
// 父组件
<ChildComponent 
  data-id="123" 
  aria-label="description"
  custom-attr="value"
/>

// 子组件
export default {
  props: ['customAttr'], // 显式声明customAttr
  mounted() {
    console.log(this.$attrs) 
    // 输出: { "data-id": "123", "aria-label": "description" }
    // customAttr不会出现在$attrs中,因为它已在props中声明
  }
}

5. $listeners

包含父组件中所有v-on事件监听器(不含.native修饰符)

typescript 复制代码
// 父组件
<ChildComponent @focus="handleFocus" @input="handleInput" />

// 子组件
<template>
  <div>
    <input v-on="$listeners" />
  </div>
</template>

6. v-model(双向绑定)

语法糖,相当于value属性+input事件

javascript 复制代码
// 父组件
<ChildComponent v-model="message" />

// 等价于
<ChildComponent :value="message" @input="message = $event" />

// 子组件实现
props: ['value'],
methods: {
  updateValue(newVal) {
    this.$emit('input', newVal)
  }
}

7. .sync修饰符

双向绑定的语法糖(Vue 2.3+)

kotlin 复制代码
// 父组件
<ChildComponent :title.sync="doc.title" />

// 子组件更新
this.$emit('update:title', newTitle)

8. parent 和 children

直接访问父/子实例(慎用)

kotlin 复制代码
// 子组件访问父组件方法
this.$parent.parentMethod()

// 父组件访问第一个子组件
this.$children[0].childMethod()

9. slots 和 scopedSlots

内容分发相关API

javascript 复制代码
// 具名插槽
<template v-slot:header>
  <h1>标题</h1>
</template>

// 作用域插槽
<template v-slot:item="slotProps">
  <span>{{ slotProps.item.text }}</span>
</template>

11. ref

给子组件添加引用标识后访问

javascript 复制代码
// 父组件
<ChildComponent ref="childComp" />

methods: {
  callChildMethod() {
    this.$refs.childComp.childMethod()
  }
}

二、跨组件通信

1. Provide 和 Inject

祖先组件提供数据,后代组件注入

javascript 复制代码
// 祖先组件
provide() {
  return {
    appContext: this.appData,
    changeContext: this.updateContext
  }
}

// 后代组件
inject: ['appContext', 'changeContext'],
methods: {
  updateData() {
    this.changeContext(newData)
  }
}

2. router(路由参数)

通过路由传递参数

php 复制代码
// 传递参数
this.$router.push({
  name: 'user',
  params: { userId: '123' },
  query: { token: 'abc' }
})

// 获取参数
const userId = this.$route.params.userId
const token = this.$route.query.token

3. Vuex(状态管理)

集中式状态管理

javascript 复制代码
// store定义
const store = new Vuex.Store({
  state: { count: 0 },
  mutations: {
    increment(state) {
      state.count++
    }
  },
  actions: {
    incrementAsync({ commit }) {
      setTimeout(() => {
        commit('increment')
      }, 1000)
    }
  }
})

// 组件中使用
computed: {
  count() {
    return this.$store.state.count
  }
},
methods: {
  increment() {
    this.$store.commit('increment')
  },
  incrementAsync() {
    this.$store.dispatch('incrementAsync')
  }
}

4. store模式(简单状态管理)

小型应用替代Vuex的简单方案

javascript 复制代码
// store.js
export const store = {
  debug: true,
  state: {
    user: null
  },
  setUser(newUser) {
    if (this.debug) console.log('setUser triggered with', newUser)
    this.state.user = newUser
  }
}

// 组件中使用
import { store } from './store'

computed: {
  currentUser() {
    return store.state.user
  }
},
methods: {
  updateUser(user) {
    store.setUser(user)
  }
}

5. Event Bus(事件总线)

创建中央事件总线进行组件间通信

javascript 复制代码
// event-bus.js
import Vue from 'vue'
export const EventBus = new Vue()

// 组件A发送事件
import { EventBus } from './event-bus'
EventBus.$emit('notification', { message: 'Hello!' })

// 组件B接收事件
import { EventBus } from './event-bus'

created() {
  EventBus.$on('notification', (payload) => {
    console.log(payload.message) // 'Hello!'
  })
},

// 组件销毁前移除监听
beforeDestroy() {
  EventBus.$off('notification')
}

三、通信方式选择指南

场景 推荐方式 备注
简单父子通信 Props/Events 最基础、最常用的方式
父子双向绑定 v-model/.sync 表单类组件常用
跨层级传递数据 Provide/Inject 适合组件库开发
全局状态管理 Vuex 中大型项目首选
临时全局事件 Event Bus 简单场景使用,注意销毁监听
路由相关数据 路由参数 页面间传递数据
简单状态共享 Store模式 小型项目替代Vuex

四、最佳实践建议

  1. ​优先使用Props/Events​​:保持组件独立性

  2. ​避免过度使用parent/children​​:会破坏组件封装性

  3. ​Vuex使用原则​​:

    • 多个组件共享的状态才放入Vuex
    • 组件私有状态应保留在组件内部
  4. ​Event Bus注意事项​​:

    • 事件名建议使用常量
    • 组件销毁前务必移除监听
  5. ​Provide/Inject适用场景​​:

    • 组件库开发
    • 深层嵌套组件通信
    • 普通业务代码慎用
相关推荐
鱼樱前端20 分钟前
今天介绍下最新更新的Vite7
前端·vue.js
coder_pig1 小时前
跟🤡杰哥一起学Flutter (三十四、玩转Flutter手势✋)
前端·flutter·harmonyos
万少1 小时前
01-自然壁纸实战教程-免费开放啦
前端
独立开阀者_FwtCoder1 小时前
【Augment】 Augment技巧之 Rewrite Prompt(重写提示) 有神奇的魔法
前端·javascript·github
yuki_uix1 小时前
AI辅助网页设计:从图片到代码的实践探索
前端
我想说一句1 小时前
事件机制与委托:从冒泡捕获到高效编程的奇妙之旅
前端·javascript
陈随易1 小时前
MoonBit助力前端开发,加密&性能两不误,斐波那契测试提高3-4倍
前端·后端·程序员
小飞悟1 小时前
你以为 React 的事件很简单?错了,它暗藏玄机!
前端·javascript·面试
中微子2 小时前
JavaScript 事件机制:捕获、冒泡与事件委托详解
前端·javascript
Whoisshutiao2 小时前
网安-XSS-pikachu
前端·安全·网络安全