Vue3 组件间通信

Vue3 中组件之间传值的方式有多种,下面我将通过示例代码介绍几种常见的传值方式。

1. 父组件向子组件传值(Props)

父组件可以通过 props 向子组件传递数据。子组件通过 props 选项接收数据,然后在模板中使用。这种方式适用于父组件向子组件单向传递数据的场景。

关键代码

父组件:

html 复制代码
<child-component :parent-message="messageToChild"></child-component>

子组件:

js 复制代码
export default {
  props: {
    parentMessage: String
  }
}

2. 子组件向父组件传值(自定义事件)

子组件可以通过 $emit 触发自定义事件,将数据传递给父组件。父组件通过 v-on 监听子组件触发的事件,接收数据。这种方式适用于子组件需要向父组件传递数据或通知父组件事件的场景。

关键代码

子组件:

js 复制代码
methods: {
  sendMessage() {
    this.$emit('child-message', 'Hello from child!')
  }
}

父组件:

html 复制代码
<child-component @child-message="receiveMessage"></child-component>

3. 使用 $attrs 透传属性

$attrs 是 Vue 组件的一个内置属性,它包含了父组件传递给子组件的属性(除了 props 定义的属性和 class、style 之外)。通过 $attrs,可以将这些属性直接传递给子组件的根元素或其他子元素。

关键代码

父组件:

html 复制代码
<child-component parentmessage="messageToChild" @input="onChildInput"></child-component>

子组件:

html 复制代码
<template>
  <div class="child">
    <h3>Child Component</h3>
    <p>Message from parent: {{ $attrs.parentmessage }}</p>
    <input type="text" v-bind="$attrs" />
  </div>
</template>

<script>
export default {
  inheritAttrs: false, // 禁用默认的属性继承行为
  // ...
}
</script>

在父组件中,我们给 <child-component> 传递了一个名为 parentmessage 的属性。

在子组件中,通过 $attrs.parentmessage 可以访问到这个属性的值。同时,通过 v-bind="$attrs",将 $attrs 中的所有属性绑定到 <input> 元素上。

注意,如果要在子组件的根元素上使用 $attrs,需要设置 inheritAttrs: false,以禁用默认的属性继承行为。

使用 $attrs 可以方便地透传属性,减少重复的 props 定义,使组件更加灵活和可复用。

4. 兄弟组件之间传值(事件总线 EventBus)

对于没有直接父子关系的组件,可以使用事件总线 EventBus 来传递数据。通过一个外部的事件总线,用 $emit 触发事件,用 $on 监听事件。这种方式适用于兄弟组件之间需要通信的场景,但在大型应用中可能会变得难以维护。

关键代码

js 复制代码
// event-bus.js
import mitt from 'mitt'
const eventBus = mitt()
export default eventBus

组件 A:

js 复制代码
import eventBus from '@/event-bus'
eventBus.emit('message', 'Hello from A!')

组件 B:

js 复制代码
import eventBus from '@/event-bus'
eventBus.on('message', (data) => {
  console.log(data) // Hello from A!
})

5. 父组件通过 refs 访问子组件

父组件可以通过 ref 属性给子组件设置一个引用名称,然后通过 $refs 访问子组件的实例,从而调用子组件的方法或访问子组件的数据。这种方式适用于父组件需要直接访问子组件的场景,但应该谨慎使用,因为它增加了组件之间的耦合度。

关键代码

父组件:

html 复制代码
<child-component ref="childRef"></child-component>
js 复制代码
mounted() {
  this.$refs.childRef.someMethod()
}

6. 通过 provide / inject 传值

父组件通过 provide 提供数据,子组件通过 inject 获取数据。这种方式适用于深度嵌套的组件,可以跨越多个层级直接传递数据。在 Vue3 中,我们可以使用 provideinject 来实现响应式数据的传递。

关键代码

父组件:

js 复制代码
import { provide, ref } from 'vue'

setup() {
  const count = ref(0)

  const incrementCount = () => {
    count.value++
  }

  provide('count', count)
  provide('incrementCount', incrementCount)

  return {
    count,
    incrementCount
  }
}

子组件:

js 复制代码
import { inject } from 'vue'

setup() {
  const count = inject('count')
  const incrementCount = inject('incrementCount')

  return {
    count,
    incrementCount
  }
}

在父组件中,通过 provide 提供了一个响应式的 count 数据和一个 incrementCount 方法。子组件通过 inject 获取了这些数据和方法,并在模板中使用。当在父组件或子组件中修改 count 的值时,另一个组件中的 count 也会同步更新,实现了响应式数据的传递。

7. Vuex 状态管理

对于大型应用,可以使用 Vuex 进行状态管理。将共享的数据存储在 Vuex 的 store 中,任何组件都可以通过 dispatch 提交 mutation 来修改状态,通过 commit 触发 action 来异步修改状态,通过 mapStatemapGetters 等辅助函数来获取状态。Vuex 适用于多个组件需要共享状态的复杂场景,但也会引入一定的复杂度。

以上就是 Vue3 中几种常见的组件间传值方式。每种方式都有其适用的场景和优缺点:

  • Props 适用于父子组件单向传值,简单直接但只能单向传递。
  • 自定义事件适用于子到父的传值,灵活方便但需要注意命名冲突。
  • $attrs 适用于透传属性,减少重复的 props 定义,使组件更加灵活和可复用。
  • 事件总线适用于兄弟组件通信,但在大型应用中可能难以维护。
  • Refs 适用于父组件直接访问子组件,但增加了耦合度。
  • Provide/inject 适用于跨层级传值,可以实现响应式数据传递。
  • Vuex 适用于多组件共享状态,功能强大但也引入了复杂度。

在实际开发中,可以根据具体需求和组件结构,灵活选择合适的传值方式,以实现组件之间清晰高效的数据共享和通信。

相关推荐
M_emory_9 分钟前
解决 git clone 出现:Failed to connect to 127.0.0.1 port 1080: Connection refused 错误
前端·vue.js·git
Ciito12 分钟前
vue项目使用eslint+prettier管理项目格式化
前端·javascript·vue.js
成都被卷死的程序员1 小时前
响应式网页设计--html
前端·html
fighting ~1 小时前
react17安装html-react-parser运行报错记录
javascript·react.js·html
老码沉思录1 小时前
React Native 全栈开发实战班 - 列表与滚动视图
javascript·react native·react.js
abments1 小时前
JavaScript逆向爬虫教程-------基础篇之常用的编码与加密介绍(python和js实现)
javascript·爬虫·python
mon_star°1 小时前
将答题成绩排行榜数据通过前端生成excel的方式实现导出下载功能
前端·excel
Zrf21913184551 小时前
前端笔试中oj算法题的解法模版
前端·readline·oj算法
老码沉思录1 小时前
React Native 全栈开发实战班 - 状态管理入门(Context API)
javascript·react native·react.js
文军的烹饪实验室2 小时前
ValueError: Circular reference detected
开发语言·前端·javascript