vue非父子组件通信

兄弟组件数据共享(event bus事件总线)

作用:非父子组件之间进行简易消息传递

EventBus的使用步骤:

① 创建 eventBus.js 模块,并向外共享一个 Vue的实例对象

 在数据发送方,调用 bus.$emit('事件名称', 要发送的数据) 方法触发自定义事件

③ 在数据接收方,调用 bus.$on('事件名称', 事件处理函数) 方法注册一个自定义事件

utils/EventBus.js

import Vue from "vue";
const bus = new Vue()
export default bus

components/MySon1.vue

<template>
    <div>
        <div class="header">
            MySon1数据发送方
            <button @click="sendFn">发送数据</button>
        </div>
    </div>
</template>

<script>
import Bus from '@/utils/EventBus'
export default {
    data() {
        return {
            msg: '你好',
        }
    },
    methods: {
        sendFn() {
            Bus.$emit('sendMsg', this.msg)
        }
    },
}
</script>

<style scoped lang="less">
.header {
    width: 300px;
    height: 300px;
    background-color: pink;
    border-radius: 5px;
    margin-bottom: 10px;
    text-align: center;

    .tit {
        font-size: 22px;
    }
}
</style>

components/MySon2.vue

<template>
    <div>
        <div class="main">
            MySon2数据接收方---{{ msgfromSon }}
        </div>
    </div>
</template>

<script>
import Bus from '@/utils/EventBus'
export default {
    data() {
        return {
            msgfromSon: '',
        }
    },
    created() {
        Bus.$on('sendMsg', (msg) => {
            this.msgfromSon = msg
        })
    }
}
</script>

<style scoped lang="less">
.main {
    width: 300px;
    height: 300px;
    background-color: blueviolet;
    border-radius: 5px;
    margin-bottom: 10px;

    .tit {
        text-align: center;
        font-size: 22px;
    }

    ul {
        li {
            text-align: left;

            span {
                float: left;
            }
        }
    }
}
</style>

App.vue

<template>
  <div id="app">
    <MySon1></MySon1>
    <MySon2></MySon2>
  </div>
</template>

<script>
import MySon1 from '@/components/MySon1.vue'
import MySon2 from '@/components/MySon2.vue'
export default {
  components: {
    MySon1,
    MySon2,
  },
  data() {
    return {

    }
  },
}

</script>

<style scoped lang="less">
#app {
  width: 800px;
  margin: 0 auto;
  background-color: #ccc;
}
</style>

 Provide 和 Inject---跨层级共享数据

基本使用

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

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

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

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

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

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

 

我们开发一个下面这样的结构: 让App.vue提供一些数据给HomeContent.vue使用在这里插入图片描述

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

export default {
  components: {
    Home
  },
  // 通过provide将数据传出
	provide() {
		return {
            color: this.color, // 简单类型(非响应式数据)
			name: this.name,
			age: this.age,
			height: this.height
            userInfo: this.userInfo, // 复杂类型 响应式--推荐
		}
	}
}

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

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

处理响应式数据(了解)

我们先来验证一个结果:如果我们修改了this.name的内容,那么使用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>

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

在这里插入图片描述

这是因为当我们修改了name之后,之前在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>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值