Vue3优雅的实现跨组件通信的常用方法总结

 更新时间:2023年11月13日 09:15:50   作者:萌萌哒草头将军  
开发中经常会遇到跨组件通信的场景,props 逐层传递的方法实在是太不优雅了,所以今天总结下可以更加简单的跨组件通信的一些方法,文中通过代码实例讲解的非常详细,需要的朋友可以参考下

前言

开发中经常会遇到跨组件通信的场景。props 逐层传递的方法实在是太不优雅了,所以今天总结下可以更加简单的跨组件通信的一些方法。

依赖注入

<!-- App.vue -->
<script setup lang="ts">
import { ref, provide } from "vue";
import Child from "./components/Child.vue";
const count = ref(0)
const updateCount = () => count.value ++
provide("count", {count, updateCount})
</script>

<template>
  <h4>公众号:萌萌哒草头将军</h4>
  <div>{{ count }}</div>
  <button @click="updateCount">change</button>
  <Child />
</template>
<!-- Child.vue -->
<template>
  <Other />
</template>
  
<script setup lang='ts'>
import Other from "./other.vue"
</script>

在 setup 组件中,使用 inject 跨组件通信是最佳的方案。所以该模式下,是没有提供event bus 事件总线。

但是在 option api 模式下,还需要额外的注册,显的有点麻烦。

<script lang='ts'>
export default {
  emits: ["some-name"]
}
</script>

属性透传

<!-- App.vue -->
<script setup lang="ts">
import { ref, provide } from "vue";
import Attr from "./components/Attr.vue";
const count = ref(0)
const updateCount = () => count.value ++
provide("count", {count, updateCount})
</script>

<template>
  <h4>公众号:萌萌哒草头将军</h4>
  <div>{{ count }}</div>
  <button @click="updateCount">change</button>
  <Attr :count="count" :updateCount="updateCount" />
</template>
<!-- Attr.vue -->
<template>
  <div>attr component</div>
  <Child v-bind="$attrs" />
</template>
  
<script setup lang='ts'>
import Child from './Child.vue';
</script>

属性透传这种方式类似于react中手动透传属性。感觉有点暴力,但是又特别方便快捷。

function App (props) {
  return <Other {...props} />
}

Vue中默认透传的属性有 style、class、key。如果子组件也存在class、style,则会自动合并class、style。

如果你的子组件是根组件时,可以省略 v-bind="$attrs"。

<template>
  <Child />
</template>

状态库

状态管理库我们以Pinia为例。

<!-- App.vue -->
<script setup lang="ts">
import Other from "./components/Other.vue";
import { useCounterStore } from "./store/index"
const state = useCounterStore()
</script>

<template>
  <h4>公众号:萌萌哒草头将军</h4>
  <div>{{ count }}</div>
  <button @click="updateCount">change</button>
  <Other />
</template>
import { defineStore } from "pinia" 
import { ref } from "vue"

export const useCounterStore = defineStore('counter', () => {
  const count = ref(0)
  function updateCount() {
    count.value++
  }

  return { count, updateCount }
})
<!-- Other.vue -->
<template>
  <div>pinia store</div>
  <div>{{ state.count }}</div>
  <button @click="state.updateCount">other change</button>
</template>
  
<script setup lang='ts'>
import { useCounterStore } from '../store';
const state = useCounterStore()
</script>

状态管理库最大的缺点是,没法使用解构语法。因为这会导致失去响应式的能力。

事件总线

事件总线(event bus)比较特殊,因为在组合式API里不支持该方式,所以下面的例子适合 Option API 组件。

<!-- App.vue -->
<script setup lang="ts">
import { ref } from "vue";
import Other from "./components/Other.vue";
const count = ref(0)
const updateCount = () => count.value ++
</script>

<template>
  <h4>公众号:萌萌哒草头将军</h4>
  <div>{{ count }}</div>
  <button @click="updateCount">change</button>
  <Other @updateCount="updateCount()" />
</template>
<!-- Other.vue -->
<template>
  <div>eventBus store</div>
  <button @click="$emit('updateCount')">other change</button>
</template>
  
<script lang='ts'>
export default {
  emits: ["updateCount"]
}
</script>

事件总线更适合传递事件。

自定义事件

但是有时候,你可能非常想使用事件总线的方式在 setup 组件中传递事件,这时候我们可以使用自定义的事件的方式实现这种功能。

下面是实现。

class EventBus {
  constructor() {
    this.events = {};
  }

  // 订阅事件
  on(eventName, callback) {
    if (!this.events[eventName]) {
      this.events[eventName] = [];
    }
    this.events[eventName].push(callback);
  }

  // 发布事件
  emit(eventName, eventData) {
    const eventCallbacks = this.events[eventName];
    if (eventCallbacks) {
      eventCallbacks.forEach(callback => {
        callback(eventData);
      });
    }
  }

  // 取消订阅事件
  off(eventName, callback) {
    const eventCallbacks = this.events[eventName];
    if (eventCallbacks) {
      this.events[eventName] = eventCallbacks.filter(cb => cb !== callback);
    }
  }
}

export const eventBus = new EventBus()
<!-- App.vue -->
<script setup lang="ts">
import { ref } from "vue";
import Other from "./components/Other.vue";
import { eventBus } from "./store/eventBus";
const count = ref(0)
const updateCount = () => count.value ++
eventBus.on("updateCount", updateCount)
</script>

<template>
  <h4>公众号:萌萌哒草头将军</h4>
  <div>{{ count }}</div>
  <button @click="updateCount">change</button>
  <Other @updateCount="updateCount()" />
</template>
<!-- Other.vue -->
<template>
  <div>eventBus</div>
  <button @click="eventBus.emit('updateCount', null)">other change</button>
</template>
  
<script setup lang='ts'>
import { eventBus } from "../store/eventBus";
</script>

当然,我们这里不止可以使用 event bus,发布订阅模式也很适合。可以参考我以前的设计模式的文章实现这个功能。

总结

每种方式都有自己的优点和缺点,根据使用场景选择最合适的才能算是最优的方案。

以上就是Vue3优雅的跨组件通信的常用方法总结的详细内容,更多关于Vue3跨组件通信的资料请关注脚本之家其它相关文章!

相关文章

  • Vue3如何解决路由缓存问题(响应路由参数的变化)

    Vue3如何解决路由缓存问题(响应路由参数的变化)

    这篇文章主要介绍了Vue3如何解决路由缓存问题(响应路由参数的变化),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • 关于.prettierrc代码格式化配置方式

    关于.prettierrc代码格式化配置方式

    这篇文章主要介绍了关于.prettierrc代码格式化配置方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10
  • Vue.js实现微信过渡动画左右切换效果

    Vue.js实现微信过渡动画左右切换效果

    这篇文章主要给大家介绍了利用Vue.js仿微信过渡动画左右切换效果的相关资料,需要用到的技术栈是Vue+Vuex。文中通过示例代码介绍的非常详细,对大家具一定的参考学习价值,需要的朋友们下面来一起看看吧。
    2017-06-06
  • vue使用原生js实现滚动页面跟踪导航高亮的示例代码

    vue使用原生js实现滚动页面跟踪导航高亮的示例代码

    这篇文章主要介绍了vue使用原生js实现滚动页面跟踪导航高亮的示例代码,滚动页面指定区域导航高亮。小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-10-10
  • Vue通过getAction的finally来最大程度避免影响主数据呈现问题

    Vue通过getAction的finally来最大程度避免影响主数据呈现问题

    这篇文章主要介绍了Vue通过getAction的finally来最大程度避免影响主数据呈现,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04
  • 浅谈VueJS SSR 后端绘制内存泄漏的相关解决经验

    浅谈VueJS SSR 后端绘制内存泄漏的相关解决经验

    这次我想给大家介绍的内存泄漏的定位方法,并非工具的使用。而是一些经验的总结,也就是我所知道的 VueJS SSR 中最容易出现内存泄漏的地方,非常具有实用价值,需要的朋友可以参考下
    2018-12-12
  • vue2中watch的用法(通俗易懂,简单明了)

    vue2中watch的用法(通俗易懂,简单明了)

    这篇文章主要给大家介绍了关于vue2中watch用法的相关资料,通过watch监听器,我们可以实时监控数据的变化,并且在数据发生改变时进行相应的操作,需要的朋友可以参考下
    2023-09-09
  • 详解如何优雅的进行Vue的状态管理

    详解如何优雅的进行Vue的状态管理

    随着项目的发展和复杂性的增加,对 Vuex 进行更深入的了解和使用就变得非常重要,本篇文章将带您探索 Vuex 的进阶使用,包括模块化、命名空间、getter 的高级用法等,需要的朋友可以参考下
    2023-09-09
  • vue项目实现中英文切换的详细步骤

    vue项目实现中英文切换的详细步骤

    这篇文章主要给大家介绍了关于vue项目实现中英文切换的详细步骤,项目中经常有中英文切换的功能,接下来就简单实现以下这个功能,文中通过代码介绍的非常详细,需要的朋友可以参考
    2023-11-11
  • 详解Vue源码学习之callHook钩子函数

    详解Vue源码学习之callHook钩子函数

    这篇文章主要介绍了详解Vue源码学习之callHook钩子函数,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-07-07

最新评论