Vue非父子组件之间的通信方式详解

 更新时间:2022年07月28日 15:36:32   作者:林有酒  
在实际业务中,除了父子组件通信外,还有很多非父子组件通信的场景,下面这篇文章主要给大家介绍了关于Vue非父子组件之间的通信方式,文中通过实例代码介绍的非常详细,需要的朋友可以参考下

非父子组件的通信

此篇讲解的是, 在学习状态管理之前, 非父子间通信的方案

在开发中,我们构建了组件树之后,除了父子组件之间的通信之外,还会有非父子组件之间的通信

这里我们主要讲两种方式

  • Provide/Inject;
  • 全局事件总线;

1.Provide和Inject

1.1基本使用

Provide/Inject用于非父子组件之间共享数据

  • 比如有一些深度嵌套的组件,子组件想要获取父组件的部分内容;
  • 在这种情况下,如果我们仍然将props沿着组件链逐级传递下去,就会非常的麻烦;

对于这种情况下,我们可以使用 Provide 和 Inject

  • 无论层级结构有多深,父组件都可以作为其所有子组件的依赖提供者;
  • 父组件有一个 provide 选项来提供数据;
  • 子组件有一个 inject 选项来开始使用这些数据;

实际上,你可以将依赖注入看作是“long range props”,除了

  • 父组件不需要知道哪些子组件使用它 provide 的 property
  • 子组件不需要知道 inject 的 property 来自哪里

我们开发一个下面这样的结构: 让App.vue提供一些数据给HomeContent.vue使用[外链图片转存失败,

在祖先组件中通过provide将数据传出, provide对应的是一个对象

export default {
  components: {
    Home
  },
  // 通过provide将数据传出
	provide() {
		return {
			name: this.name,
			age: this.age,
			height: this.height
		}
	}
}

在后代元素中, 通过inject接收祖先传递的数据, inject对应的是一个数组

export default {
  inject: ["name", "age", "height"]
}

1.2处理响应式数据(了解)

我们先来验证一个结果:如果我们修改了this.names的内容,那么使用length的子组件会不会是响应式的?

<template>
  <div class="app">
    <home />
    <h2>{{ name }}</h2>
    <button @click="btnClick">按钮</button>
  </div>
</template>

<script>
  import Home from './Home.vue'

  export default {
    components: {
      Home
    },
    data() {
      return {
        name: "chenyq",
        age: 18,
        height: 1.88,
      }
    },
    // 通过provide将数据传出
    provide() {
      return {
        name: this.name,
        age: this.age,
        height: this.height
      }
    },
    methods: {
      btnClick() {
        this.name = "kaisa"
      }
    },
  }
</script>

我们会发现对应的子组件中是没有反应的

这是因为当我们修改了names之后,之前在provide中引入的 this.name 本身并不是响应式的

那么怎么样可以让我们的数据变成响应式的呢?

  • 非常的简单,我们可以使用响应式的一些API来完成这些功能,比如说computed函数;
  • 当然,这个computed是vue3的新特性,在后面我会专门讲解,这里大家可以先直接使用一下;
import { computed } from 'vue'

export default {
  components: {
    Home
  },
  data() {
    return {
      name: "chenyq",
      age: 18,
      height: 1.88,
    }
  },
  // 通过provide将数据传出
  provide() {
    return {
      name: computed(() => this.name),
      age: this.age,
      height: this.name
    }
  },
  methods: {
    btnClick() {
      this.name = "kaisa"
    }
  },
}

注意:我们在使用name的时候需要获取其中的value

这是因为computed返回的是一个ref对象,需要取出其中的value来使用;

<template>
  <div class="home-content">
    <h2>名字: {{ name.value }}, 年龄: {{ age}}, 身高: {{ height}}</h2>
  </div>
</template>

2.全局事件总线

Vue3从实例中移除了 o n 、 on、 on、off 和 $once 方法,所以我们如果希望继续使用全局事件总线,要通过第三方的库

  • Vue3官方有推荐一些库,例如 mitt 或 tiny-emitter, 这两个库虽然不再维护, 但还是可以使用的;
  • 这里我们主要讲解一下 hy-event-store 的使用, 是前端大神coderwhy封装的他自己的库;

首先,我们需要先安装这个库npm install hy-event-store

其次,我们可以封装一个工具eventbus.js

import { HyEventBus } from "hy-event-store";
const eventBus = new HyEventBus()
export default eventBus

在项目中导入后可以使用它们

  • 我们在App.vue中监听事件;
  • 我们在Banner.vue中触发事件;

Banner中触发事件:

<template>
  <div class="home-content">
    <button @click="btnClick">按钮</button>
  </div>
</template>

<script>
  import eventBus from './utils/event-bus'

  export default {
    methods: {
      btnClick() {
        console.log("myEvent事件被监听")
				// 发送事件到事件总线上
        eventBus.emit("myEvent", "chenyq", 18, 1.88)
      }
    },
  }
</script>

App中监听事件:

<script>
  import eventBus from './utils/event-bus'
  import Home from './Home.vue'

  export default {
    components: {
      Home
    },
    created() {
			// 监听事件总线上的事件
      eventBus.on("myEvent", (name, age, height) => {
        console.log(name, age, height)
      })
    },
  }
</script>

总结

到此这篇关于Vue非父子组件之间的通信方式的文章就介绍到这了,更多相关Vue非父子组件通信内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue中render函数和h函数以及jsx的使用方式

    vue中render函数和h函数以及jsx的使用方式

    这篇文章主要介绍了vue中render函数和h函数以及jsx的使用方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • vue实现拖动左侧导航栏变大变小

    vue实现拖动左侧导航栏变大变小

    这篇文章主要为大家详细介绍了vue实现拖动左侧导航栏变大变小,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • 详解Vue 实例中的生命周期钩子

    详解Vue 实例中的生命周期钩子

    这篇文章主要介绍了详解Vue 实例中的生命周期钩子,在Vue的整个生命周期中,它提供了一些生命周期钩子,给了我们执行自定义逻辑的机会。
    2017-03-03
  • vue3 使用defineExpose的实例详解

    vue3 使用defineExpose的实例详解

    这篇文章主要介绍了vue3 使用defineExpose的相关知识,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-03-03
  • vue 项目常用加载器及配置详解

    vue 项目常用加载器及配置详解

    本文介绍了vue 项目常用加载器及配置详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • vue-router使用next()跳转到指定路径时会无限循环问题

    vue-router使用next()跳转到指定路径时会无限循环问题

    这篇文章主要介绍了vue-router使用next()跳转到指定路径时会无限循环问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • vue中实时监听div元素盒子的宽高方法

    vue中实时监听div元素盒子的宽高方法

    这篇文章主要给大家介绍了关于vue中如何实时监听div元素盒子的宽高的相关资料,在Vue中你可以使用Vue的计算属性和侦听器来动态监测元素的高度,文中给出了简单代码示例,需要的朋友可以参考下
    2023-09-09
  • vue本地打开build后生成的dist文件夹index.html问题

    vue本地打开build后生成的dist文件夹index.html问题

    这篇文章主要介绍了vue本地打开build后生成的dist文件夹index.html问题,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友参考下吧
    2019-09-09
  • 解析使用useDark(),发现transition 动画失效

    解析使用useDark(),发现transition 动画失效

    这篇文章主要为大家介绍了使用useDark(),发现transition动画失效的示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05
  • 浅谈Vue-cli单文件组件引入less,sass,css样式的不同方法

    浅谈Vue-cli单文件组件引入less,sass,css样式的不同方法

    下面小编就为大家分享一篇浅谈Vue-cli单文件组件引入less,sass,css样式的不同方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-03-03

最新评论