vue中非父子组件的通信你了解吗

 更新时间:2022年02月13日 17:17:39   作者:卖菜的小白  
这篇文章主要为大家详细介绍了vue中非父子组件通信,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

我们总结了父子组件通信方式有:props + emit。这里我们将总结一下,非父子组件通信方式,这里还不涉及到Vuex。

如果存在祖孙组件,我们可以通过ProvideInject进行通信。

如果不是祖孙组件,也不是父子组件,我们可以采用Mitt全局事件总线第三方库来实现。

一、Provide和Inject

ProvideInject用于非父子组件之间共享数据,比如有一些深度嵌套的组件,子组件想要获取父组件的数据,如果不存在Provide和Inject选项,我们可以通过props进行一次传递数据,但是这样做太过于繁琐。

对于上述情况,我们可以使用ProvideInject无论组件结构嵌套有多深,父组件都可以作为子组件数据的提供者。

父组件存在Provide来提供数据。

子组件存在Inject来获取数据。

在实际过程中,父组件不知道哪个子组件使用其数据,子组件也不知道使用的是哪个父组件的数据。

Provide和Inject的基本使用

//父组件
<template>
  <div>
    <Content></Content>
  </div>
</template>
<script>
import Content from "./components/Content.vue";
export default {
  data() {
    return {};
  },
  provide:{
    name:"张三",
    age:20
  },
  components: {
    Content
  }
};
</script>
<style scoped></style>
//子组件
<template>
  <div>
    <h1>这里是Content组件</h1>
    <h1>{{ name }} -- {{age}}</h1>
    <ContentBase></ContentBase>
  </div>
</template>
<script>
import ContentBase from "./ContentBase.vue";
export default {
  data() {
    return {};
  },
  components: {
    ContentBase
  },
  inject:["name", "age"]
};
</script>
<style scoped></style>
//孙组件
<template>
  <div>
      <h1>这里是contentBase组件</h1>
      <h1>{{name}} -- {{age}}</h1>
  </div>
</template>
<script>
export default {
  data() {
    return {};
  },
  inject: ["name", "age"]
};
</script>
<style scoped>
</style>

最终显示结果为:

在这里插入图片描述

二、Provide和Inject的另一种写法

我们思考一种情况,如果Provide拿到的数据,是从data拿到的数据,此时如果获取? 此时this可以使用吗?

<template>
  <div>
    <Content></Content>
  </div>
</template>
<script>
import Content from "./components/Content.vue";
export default {
  data() {
    return {
      source: ["111","222", "333"]
    };
  },
  provide:{
    name:"张三",
    age:20,
    res: this.source.length   //我们在此时增加res,想要通过this.source.length拿到数组的长度
  },
  components: {
    Content
  }
};
</script>
<style scoped></style>

该结果是错误的。

在这里插入图片描述

报错信息显示,我们从undefined上读取属性,此时this为undefined。原因:从上面代码我们可以看出,this指向的是undefiend(因为this执行最外层)。

解决方法

我们将Provide设置为一个函数,并且返回一个对象,如下代码所示:

<template>
  <div>
    <Content></Content>
  </div>
</template>
<script>
import Content from "./components/Content.vue";
export default {
  data() {
    return {
      source: ["111", "222", "333"],
    };
  },
  provide() {
    return {
      name: "张三",
      age: 20,
      res: this.source.length,
    };
  },
  components: {
    Content,
  },
};
</script>
<style scoped></style>

显示结果:

在这里插入图片描述

此时我们再思考一个问题,如果我们向data数组中新增一个元素,在其他地方获取的数组长度会跟随变化吗?

<template>
  <div>
    <Content></Content>
    <button @click="addOneItem">点击</button>
  </div>
</template>
<script>
import Content from "./components/Content.vue";
export default {
  data() {
    return {
      source: ["111", "222", "333"],
    };
  },
  provide() {
    return {
      name: "张三",
      age: 20,
      res: this.source.length,
    };
  },
  components: {
    Content,
  },
  methods:{  //在这里添加点击事件
    addOneItem() {
      this.source.push("nnn")
      console.log(this.source)
    }
  }
};
</script>
<style scoped></style>

在这里插入图片描述

在这里插入图片描述

结果如上图所示,可以看到数据是被添加进去的,但是子组件并没有检测到数据的变化。

此时我们可以使用computed来检测this.source.length的变化,使用代码如下所示。

<template>
  <div>
    <Content></Content>
    <button @click="addOneItem">点击</button>
  </div>
</template>
<script>
import Content from "./components/Content.vue";
import { computed } from "vue"   //从vue中引入computed
export default {
  data() {
    return {
      source: ["111", "222", "333"],
    };
  },
  provide() {
    return {
      name: "张三",
      age: 20,
      res: computed(() => this.source.length), //在这里添加computed
    };
  },
  components: {
    Content,
  },
  methods:{
    addOneItem() {
      this.source.push("nnn")
      console.log(this.source)
    }
  }
};
</script>
<style scoped></style>

在这里插入图片描述

在这里插入图片描述

因为我们通过computed获取的是一个对象,此时我们通过value属性拿到值。

三、全局事件总线mitt库

在vue2时,如果我们使用事件总线可以使用this.$bus = new Vue()也就是实例化一个vue对象。但是我们在vue3中不能这样用。所以我们采用第三方库来实现组件之间的通信。这个第三方库为mitt

一、安装

npm install mitt

在文件中引入并且进行初始化导出。

import mitt from "mitt";
const emitter = new mitt()
export default emitter

监听事件,第一个参数是事件名,第二个参数是回调函数。

    emitter.on("why", (data) => {
      console.log(data)
    })
    //*表示可以监听全部的事件。
    emitter.on("*", (type, data) => {
      console.log(type, data)
    })

在这里插入图片描述

取消事件

//取消emitter中所有的监听
emitter.all.clear()
//或者
//定义一个函数
function onFoo(){}
emitter.on("foo", onFoo)
emitter.on("foo", onFoo)

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!   

相关文章

  • vue3+vite兼容低版本的白屏问题详解(安卓7/ios11)

    vue3+vite兼容低版本的白屏问题详解(安卓7/ios11)

    这篇文章主要给大家介绍了关于vue3+vite兼容低版本的白屏问题的相关资料,还给大家介绍了vue打包项目以后白屏和图片加载不出来问题的解决方法,需要的朋友可以参考下
    2022-12-12
  • vue中引入mxGraph的步骤详解

    vue中引入mxGraph的步骤详解

    本文分步骤给大家介绍了vue中引入mxGraph的方法,非常不错,给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-05-05
  • 解决node-sass安装报错无python等情况

    解决node-sass安装报错无python等情况

    在国内安装node-sass常因无法稳定连接GitHub而失败,解决方法包括手动下载对应的binding.node文件并放入缓存目录,操作步骤详细,适合非Python用户,无需额外环境配置
    2024-10-10
  • vue项目在线上服务器访问失败原因分析

    vue项目在线上服务器访问失败原因分析

    这篇文章主要介绍了vue项目在线上服务器访问失败原因分析,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • vue中循环表格数据出现数据联动现象(示例代码)

    vue中循环表格数据出现数据联动现象(示例代码)

    在Vue中循环生成表格数据时,可能会遇到数据联动的现象,即修改一个表格中的数据后,其他表格的数据也会跟着变化,这种现象通常是因为所有表格的数据引用了同一个对象或数组导致的,本文介绍vue中循环表格数据出现数据联动现象,感兴趣的朋友一起看看吧
    2024-11-11
  • Vue仿百度搜索功能

    Vue仿百度搜索功能

    这篇文章主要为大家详细介绍了Vue仿百度搜索功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-12-12
  • vue2.0 + ele的循环表单及验证字段方法

    vue2.0 + ele的循环表单及验证字段方法

    今天小编就为大家分享一篇vue2.0 + ele的循环表单及验证字段方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-09-09
  • vue+iview框架实现左侧动态菜单功能的示例代码

    vue+iview框架实现左侧动态菜单功能的示例代码

    这篇文章主要介绍了vue+iview框架实现左侧动态菜单功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07
  • vue实现动态路由的详细代码示例

    vue实现动态路由的详细代码示例

    动态路由,动态即不是写死的,是可变的,下面这篇文章主要给大家介绍了关于vue实现动态路由的详细代码示例,文中通过图文以及代码介绍的非常详细,需要的朋友可以参考下
    2024-01-01
  • 代码详解Vuejs响应式原理

    代码详解Vuejs响应式原理

    这篇文章主要介绍了代码详解Vuejs响应式原理的基础知识,有兴趣的朋友们参考学习下吧。
    2017-12-12

最新评论