Vue组件通信方式详解(全面版)

170 篇文章 3 订阅
72 篇文章 11 订阅

Vue应用开发中,组件通信是一个重要的话题。不同的组件可能需要在不同的情况下进行数据传递和交互。Vue提供了多种方式来实现组件通信,每种方式都有其适用的场景。本文将详细介绍Vue中实现组件通信的各种方式,并为每种方式提供通俗易懂的代码示例。

公众号:Code程序人生,个人网站:https://creatorblog.cn

Props

Props是父组件向子组件传递数据的一种方式。子组件通过在声明中指定props属性来接收父组件传递的数据。

<!-- ParentComponent.vue -->
<template>
  <ChildComponent message="Hello from parent!" />
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent,
  },
};
</script>

<!-- ChildComponent.vue -->
<template>
  <div>{{ message }}</div>
</template>

<script>
export default {
  props: ['message'],
};
</script>

自定义事件

子组件可以使用$emit触发一个自定义事件,父组件通过在子组件上使用v-on监听该事件并执行相应的方法。

<!-- ChildComponent.vue -->
<template>
  <button @click="sendMessage">Send Message to Parent</button>
</template>

<script>
export default {
  methods: {
    sendMessage() {
      this.$emit('message-sent', 'Hello from child!');
    },
  },
};
</script>

<!-- ParentComponent.vue -->
<template>
  <ChildComponent @message-sent="handleMessage" />
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent,
  },
  methods: {
    handleMessage(message) {
      console.log(message); // Output: "Hello from child!"
    },
  },
};
</script>

事件总线(Event Bus)

事件总线是一个空的Vue实例,可以用于在任何组件间发布和订阅事件。

<!-- EventBus.js -->
import Vue from 'vue';
export const eventBus = new Vue();

<!-- FirstComponent.vue -->
<template>
  <button @click="sendMessage">Send Message to SecondComponent</button>
</template>

<script>
import { eventBus } from './EventBus.js';

export default {
  methods: {
    sendMessage() {
      eventBus.$emit('message-sent', 'Hello from first component!');
    },
  },
};
</script>

<!-- SecondComponent.vue -->
<template>
  <div>{{ message }}</div>
</template>

<script>
import { eventBus } from './EventBus.js';

export default {
  data() {
    return {
      message: '',
    };
  },
  created() {
    eventBus.$on('message-sent', (message) => {
      this.message = message;
    });
  },
};
</script>

Vuex

VuexVue的状态管理库,用于在不同组件间共享状态。

<!-- store/index.js -->
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;
    },
  },
});

<!-- FirstComponent.vue -->
<template>
  <button @click="updateMessage">Update Message in SecondComponent</button>
</template>

<script>
import { mapMutations } from 'vuex';

export default {
  methods: {
    ...mapMutations(['updateMessage']),
    updateMessage() {
      this.updateMessage('Hello from first component!');
    },
  },
};
</script>

<!-- SecondComponent.vue -->
<template>
  <div>{{ message }}</div>
</template>

<script>
import { mapState } from 'vuex';

export default {
  computed: {
    ...mapState(['message']),
  },
};
</script>

$parent 和 $children

Vue提供了$parent$children属性来访问父组件和子组件的实例。

<!-- ParentComponent.vue -->
<template>
  <div>
    <ChildComponent />
  </div>
</template>

<!-- ChildComponent.vue -->
<template>
  <button @click="sendMessage">Send Message to Parent</button>
</template>

<script>
export default {
  methods: {
    sendMessage() {
      this.$parent.message = 'Hello from child!';
    },
  },
};
</script>

依赖注入

依赖注入是一种高级的通信方式,适用于祖先组件向后代组件传递数据,而不需要显式地通过props传递。

<!-- AncestorComponent.vue -->
<template>
  <DescendantComponent />
</template>

<script>
import { provide } from 'vue';
import DescendantComponent from './DescendantComponent.vue';

export default {
  components: {
    DescendantComponent,
  },
  setup() {
    provide('message', 'Hello from ancestor!');
  },
};
</script>

<!-- DescendantComponent.vue -->
<template>
  <div>{{ message }}</div>
</template>

<script>
import { inject } from 'vue';

export default {
  setup() {
    const message = inject('message');
    return {
      message,
    };
  },
};
</script>

$attrs 和 $listeners

$attrs$listeners 允许将父组件中非 prop 特性和事件传递给子组件,用于更灵活的组件封装。

<!-- ParentComponent.vue -->
<template>
  <ChildComponent title="Hello" @custom-event="handleEvent" />
</template>

<!-- ChildComponent.vue -->
<template>
  <div>
    <h1>{{ title }}</h1>
    <button @click="$emit('custom-event', 'Custom Event')">Click</button>
  </div>
</template>

<script>
export default {
  props: ['title'],
};
</script>

插槽(Slots)

插槽允许父组件向子组件传递内容,而不仅仅是数据。

<!-- ParentComponent.vue -->
<template>
  <ChildComponent>
    <p>Slot content from parent</p>
  </ChildComponent>
</template>

<!-- ChildComponent.vue -->
<template>
  <div>
    <slot></slot>
  </div>
</template>

$refs

$refs 允许父组件访问子组件的实例,从而进行直接通信。

<!-- ParentComponent.vue -->
<template>
  <div>
    <ChildComponent ref="childRef" />
    <button @click="sendMessageToChild">Send Message to Child</button>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent,
  },
  methods: {
    sendMessageToChild() {
      this.$refs.childRef.receiveMessage('Hello from parent!');
    },
  },
};
</script>

<!-- ChildComponent.vue -->
<template>
  <div>{{ message }}</div>
</template>

<script>
export default {
  data() {
    return {
      message: '',
    };
  },
  methods: {
    receiveMessage(message) {
      this.message = message;
    },
  },
};
</script>

localStorage或sessionStorage

浏览器缓存在一定程序上也可以帮助我们实现组件通信,甚至跨页面、跨窗口通信,但是在Vue项目中有很多更优秀的通信方式,不是很建议使用localStoragesessionStorage来实现。

// 在一个页面中存储数据
localStorage.setItem('message', 'Hello from localStorage');

// 在另一个页面中获取数据
const message = localStorage.getItem('message');
console.log(message); // "Hello from localStorage"

总结

组件通信是我们日常开发中最常见的功能,可以这样说,有组件的地方就有组件通信的需求,而现在所有框架都朝着组件化、工程化的方向发展,所以组件通信是我们必须掌握的。

上述内容详细介绍了Vue中实现组件通信的多种方式,提供了基本的代码示例。它们有各自的使用场景,大家可以根据不同的场景和需求,选择合适的通信方式可以让你的Vue应用更加高效和可维护。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CreatorRay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值