vue 组件通信的多种方式

目录
  • 前言
  • 一、vuex
  • 二、eventBus
  • 三、props/emit
  • 四、$parent/$children
  • 五、$attrs/$listeners
  • 六、provide/inject

前言

在vue中,​ 组件的关系不外乎以下三种:

组件是需要通信的,在开发中,常用到的通信方式有:vuex、eventBus、以及props与emit、$parent与$children,除此之外,还有provide与inject、$attrs与$listeners等。

一、vuex

这个相信大家用的很多了,简单回顾一下:

  • State:放状态的地方
  • Mutation:唯一修改状态的地方,不支持异步
  • Action:通过调用Mutation中的方法来达到修改状态的目的,支持异步
  • Getter:可以理解为计算属性
  • Module:模块,每个模块拥有自己的 state、mutation、action、getter

简单的使用这里不赘述,提一下module里面的命名空间。

如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名

这样,在使用的时候我们就可以这样用了:

二、eventBus

这个称为‘事件总线’,简单看下是怎么使用的:

  • 初始化

首先是初始化一个eventBus,可以绑定到vue原型上,也可以绑定到window对象上,还可以抽出来当做一个模块,在需要的时候再引入。这里直接绑定到vue原型上:

  • 创建事件和删除事件

在需要的组件上创建和删除事件:

  • 触发事件

最后就是在需要的地方触发事件了

三、props/emit

这个不用多说了,父子通信用的最多的应该就是这个了。当然,如果以子组件为跳板,也可以做到祖孙之间通信,不过比较麻烦。不建议这样操作。

四、$parent/$children

$parent直接访问的就是父实例,而$children则返回的是实例数组。所以我一般都是$parent搭配$refs使用。

五、$attrs/$listeners

这两个可能会用的比较少,来看下官网的介绍:

怎么理解呢,简单来讲就是,$attrs接收除了prop、style、class之外的所有绑定属性,$listeners则接收除了被.native修饰的所有绑定事件。具体来看下例子:

<template>
  <div>
    <p>父组件</p>
    <input type="text" v-model="formData.inputValue" />
    <p>子组件</p>
    <Son
      :inputValue="formData.inputValue"
      :otherValue="otherValue"
      @success="success"
      @input.native="handleInput"
      v-bind="$attrs"
      v-on="$listeners"
    ></Son>
  </div>
</template>
<script>
import Son from "./son.vue";
export default {
  components: { Son },
  provide() {
    return {
      father: this.formData,
    };
  },
  data() {
    return {
      formData: {
        inputValue: "123",
      },
      otherValue: 999,
    };
  },
  methods: {
    success(data) {
      console.log(data);
    },
    handleInput() {},
  },
};
</script>
<template>
  <div>
    <input type="text" v-model="inputValue" @change="handleChange" />
  </div>
</template>
<script>
export default {
  props: {
    inputValue: String,
  },
  created() {
    console.log(this.$attrs, "son---$attrs");
    console.log(this.$listeners, "son---$listeners");
  },
  methods: {
    handleChange() {
      this.father.inputValue = this.inputValue;
    },
  },
};
</script>

按照之前的理解,$attrs应该只能接收到otherValue,$listeners则只能接收到success事件,看下打印结果:

结果确实也是这样的。除此之外,还可传递给孙组件:

<template>
  <div>
    <input type="text" v-model="inputValue" @change="handleChange" />
    <GrandSon v-bind="$attrs" v-on="$listeners"></GrandSon>
  </div>
</template>
<script>
import GrandSon from "./grandSon.vue";
export default {
  components: { GrandSon },
  props: {
    inputValue: String,
  },
  created() {
    console.log(this.$attrs, "son---$attrs");
    console.log(this.$listeners, "son---$listeners");
  },
  methods: {
    handleChange() {
      this.father.inputValue = this.inputValue;
    },
  },
};
</script>
<template>
  <div>
    <input type="text" v-model="inputValue" @change="handleChange" />
  </div>
</template>
<script>
export default {
  props: {
    inputValue: String,
  },
  created() {
    console.log(this.$attrs, "grandSon---$attrs");
    console.log(this.$listeners, "grandSon---$listeners");
  },
  methods: {
    handleChange() {
      this.father.inputValue = this.inputValue;
    },
  },
};
</script>

通过这种方式,祖孙之间也实现了通信。

六、provide/inject

provide/inject可以在一个祖先组件中向它的所有后辈组件注入一个依赖,只要上下游关系成立就能生效。简单的理解就是provide是注入数据,inject是获取数据。所以provide是用于父组件,inject是用于子孙组件。provide应该是一个对象或者返回一个对象的函数,inject应该是一个字符串数组或者一个对象。官网提到这么一句话:

提示:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。

这句话怎么理解呢?字面理解就是你要想在上下游传递的那个数据是可响应的,那么就应该以对象的形式传递,先试一下以基本数据类型的形式传递,看下例子:
父组件:

<template>
  <div>
    <p>父组件</p>
    <input type="text" v-model="inputValue" />
    <p>子组件</p>
    <Son></Son>
    <p>孙组件</p>
    <GrandSon></GrandSon>
  </div>
</template>
<script>
import Son from "./son.vue";
import GrandSon from "./grandSon.vue";
export default {
  components: { Son, GrandSon },
  provide() {
    return {
      father: this.inputValue,
    };
  },
  data() {
    return {
      inputValue: "123",
    };
  },
};
</script>

子组件:

<template>
  <div>
    <input type="text" v-model="inputValue" @change="handleChange" />
  </div>
</template>
<script>
export default {
  inject: ["father"],
  data() {
    return {
      inputValue: "",
    };
  },
  watch: {
    father(val) {
      console.log(val, "val");
      this.inputValue = val;
    },
  },
  created() {
    console.log(this, "this");
  },
  methods: {
    handleChange() {
      this.father.inputValue = this.inputValue;
    },
  },
};
</script>

在子组件打印this:

可以看到,父组件的inputValue值是被注入到子组件当中的。但却监听不到这个father。

然后,我们改成以对象的形式进行注入:

<template>
  <div>
    <p>父组件</p>
    <input type="text" v-model="formData.inputValue" />
    <p>子组件</p>
    <Son></Son>
    <p>孙组件</p>
    <GrandSon></GrandSon>
  </div>
</template>
<script>
import Son from "./son.vue";
import GrandSon from "./grandSon.vue";
export default {
  components: { Son, GrandSon },
  provide() {
    return {
      father: this.formData,
    };
  },
  data() {
    return {
      formData: {
        inputValue: "123",
      },
    };
  },
};
</script>
<template>
  <div>
    <input type="text" v-model="inputValue" @change="handleChange" />
  </div>
</template>
<script>
export default {
  inject: ["father"],
  data() {
    return {
      inputValue: "",
    };
  },
  watch: {
    'father.inputValue'(val){
      console.log(val, "val");
      this.inputValue = val;
    },
  },
  created() {
    console.log(this, "this");
  },
  methods: {
    handleChange() {
      this.father.inputValue = this.inputValue;
    },
  },
};
</script>

这个时候我们看下打印的this以及效果:

这样就可以实现数据的响应了。这里有一个点需要注意,如果在父组件中将整个父组件的this注入到后代组件中,在后代组件中是不能通过深度监听来监听这个注入的对象的,会报堆栈溢出的错误。所以这里我用的是this.formData的形式注入。这样在子孙组件中可以通过'father.inputValue'这样的形式监听,也可以通过这样的形式:

father: {
      handler(val) {
        console.log(val);
      },
      deep: true,
    },

至于为什么会导致这个问题,我们先看下深度监听的实现方式:

这段注释什么意思呢,简单理解就是vue是通过递归遍历对象里面的每一个属性,将是对象的属性收集起来进行监听。众所周知,递归是很容易引起堆栈溢出的,而看下this对象就不难理解为什么会导致堆栈溢出了(太多了,而且是层层嵌套下去的)。
以上就是Vue组件通信的几种方式,如果还要在扯一扯,浏览器的缓存也可以作为一种手段。。。

到此这篇关于vue 组件通信的几种方式的文章就介绍到这了,更多相关vue 组件通信内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • vue中组件通信详解(父子组件, 爷孙组件, 兄弟组件)

    vue中我们常常用到组件. 那么组件总体可以分为如下的几种关系. 父子组件, 爷孙组件, 兄弟组件. 这几种组件之间是如何通信的呢? 父子组件通信 根据vue中的文档可知, 组件的props属性用于接收父组件传递的信息. 而子组件想要向父组件传递信息, 可以使用$emit事件. 我们定义两个组件, 一个为父组件名为father, 另外一个为子组件child. 子组件通过props属性接收父组件传递的值, 这个值为fname, 是父组件的名字. 点击子组件的按钮, 触发toFather事件, 向父

  • 详解Vue3的七种组件通信方式

    目录 写在前面 举一个栗子 Props方式 emit方式 v-model方式 refs方式 provide/inject方式 事件总线 状态管理工具 写在前面 本篇文章是全部采用的<script setup>这种组合式API写法,相对于选项式来说,组合式API这种写法更加自由,具体可以参考Vue文档对两种方式的描述. 本篇文章将介绍如下七种组件通信方式: props emit v-model refs provide/inject eventBus vuex/pinia(状态管理工具) 开始搞

  • 解决父子组件通信的三种Vue插槽

    目录 前言 环境准备 Category组件 App组件 一.默认插槽 二.具名插槽 三.作用域插槽 总结 前言 插槽可以说是 Vue 中非常重要的一部分吧,在我学习和练习的过程中,当组件搭配着插槽一起使用的时候,会发挥的更好一些.更多时候也会更加方便. 今天介绍Vue中三种插槽吧:默认插槽.具名插槽.作用域插槽. 环境准备 先搭个初始环境给大家看看哈.一步一步讲完这个插槽. 就是写了一个类别组件,分别渲染这三种数据. Category组件 <template> <div class=&q

  • vue实现组件通信的八种方法实例

    目录 1.props 父组件--->子组件通信 2.$emit 子组件--->父组件传递 3.bus(事件总线) 兄弟组件通信 4.$parent.$children 直接访问组件实例 5.$refs 6.provide/inject(提供/注入) 多组件或深层次组件通信 7.slot(slot-scope作用域插槽) 子元素-->父元素(类似于通信) 8.vuex状态管理 总结 对于vue来说,组件之间的消息传递是非常重要的,下面是我对组件之间消息传递的常用方式的总结 1.props

  • Vue组件通信方法案例总结

    目录 一.父组件向子组件传值(props) 二.子组件向父组件传值($emit) 三.兄弟组件传值(EventBus) 1. 初始化(new Vue()) 2. 发送事件($emit()) 3. 接收事件($on()) 4. 移除事件监听者 四.Vuex 一.父组件向子组件传值(props) 步骤: 在父组件中通过 v-bind 将数据传给子组件 在子组件中通过 props 接收父组件传递过来的数据 <div id="app"> <!-- 1.通过 v-bind 将数

  • Vue3的7种种组件通信详情

    目录 1.Vue3 组件通信方式 2.Vue3 通信使用写法 2.1 props 2.2 $emit 2.3 expose / ref 2.4 attrs 2.5 v-model 2.6 provide / inject 2.7 Vuex 1.Vue3 组件通信方式 props $emit expose / ref $attrs v-model provide / inject Vuex 2.Vue3 通信使用写法 2.1 props 用 props 传数据给子组件有两种方法,如下 方法一:混合

  • vue 组件通信的多种方式

    目录 前言 一.vuex 二.eventBus 三.props/emit 四.$parent/$children 五.$attrs/$listeners 六.provide/inject 前言 在vue中,​ 组件的关系不外乎以下三种: 组件是需要通信的,在开发中,常用到的通信方式有:vuex.eventBus.以及props与emit.$parent与$children,除此之外,还有provide与inject.$attrs与$listeners等. 一.vuex 这个相信大家用的很多了,简

  • vue组件通信的多种方法详解

    目录 1. 父传子 2. 子传父 3. 非父子组件传值 4. vuex 5. refs 6. $children 7. $parent 8. provide & inject 9. $attrs 10. $listeners 总结 说起组件通信,可能大家耳熟能详的有以下5种: 1. 父传子 父组件通过自定义属性给子组件传值,子组件用props接收 2. 子传父 父组件在子组件标签上自定义事件,子组件通过$emit来触发自定义事件,并且可以传递参数 3. 非父子组件传值 eventBus事件总线:

  • vue2.0组件之间传值、通信的多种方式(干货)

    Vue中组件这个特性让不少前端er非常喜欢,我自己也是其中之一,它让前端的组件式开发更加合理和简单.这次我们就来聊一聊vue2.0组件之间传值.通信的多种方式. 一.通过路由带参数进行传值 ①两个组件 A和B,A组件通过query把orderId传递给B组件(触发事件可以是点击事件.钩子函数等) this.$router.push({ path: '/conponentsB', query: { orderId: 123 } }) // 跳转到B ②在B组件中获取A组件传递过来的参数 this.

  • Vue.js 父子组件通信的十种方式

    面试官:Vue 中父子组件通信有哪些方式? 自己先想一分钟. 无可否认,现在无论大厂还是小厂都已经用上了Vue.js 框架,简单易上手不说,教程详尽,社区活跃,第三方套件还多.真的是前端开发人员必备技能.而且在面试当中也往往会问到关于 Vue 方面的各种问题,其中大部分面试官会问到如上这种问题. 最近一直在做 Vue项目代码层面上的优化,说实话,优化别人的代码真是件痛苦的事情,功能实现尚且不说,就说代码规范我就能再写出一篇文章来.真的是无规范不成方圆,规范这个东西太重要了!有点扯了,回到主题,咳

  • Vue组件通信之父传子与子传父详细讲解

    目录 父组件传递给子组件 浅谈Props 子组件传递给父组件 父组件传递给子组件 父组件传递给子组件:通过props属性: 子组件传递给父组件:通过$emit触发事件: 这里我们知道,父组件有一些数据需要子组件来进行展示,那我们可以通过props来完成组件之间的通信 通过props来完成组件之间的通信 浅谈Props 那么什么是Props呢? 作用:接受父组件传递过来的属性 Props是你可以在组件上注册一些自定义的attribute(属性): 父组件给这些attribute(属性)赋值,子组件

  • vue组件通信传值操作示例

    本文实例讲述了vue组件通信传值操作.分享给大家供大家参考,具体如下: 父子组件通信: 子组件 <template> <div> <h3 @click="alerrt"> 我是子组件一</h3> <span>{{parentMessage}}</span> </div> </template> <script> export default{ props: ['parentMes

  • vue组件传值的实现方式小结【三种方式】

    本文实例讲述了vue组件传值的实现方式.分享给大家供大家参考,具体如下: 前言 vue的组件传值分为三种方式:父传子.子传父.非父子组件传值 引用官网的一句话:父子组件的关系可以总结为 prop 向下传递,事件向上传递 父组件通过 prop 给子组件下发数据,子组件通过事件给父组件发送消息,如下图所示: 下面我们就开始用代码(一言不合就上代码)详细的介绍vue组件传值的三种方式 1.父传子 子组件的代码: <template> <div id="container"&

  • Vue组件通信深入分析

    目录 一.组件间的通信方式分类 二.props传递数据 三.$emit 触发自定义事件 四.ref标记 五.EventBus事件总线 六.$parent 或 $root 七.vuex 八.总结 一.组件间的通信方式分类 父子组件之间的通信: 兄弟组件之间的通信: 祖孙与后代组件之间的通信: 非关系组件之间的通信. 二.props传递数据 适用场景:父组件传递数据给子组件: 子组件设置props属性,定义接收父组件传递过来的参数: 父组件在使用子组件标签中通过字面量来传递值 Person.vue

  • 详解vue组件通信的三种方式

    1. 第一种方式就是官方推荐的 官方推荐方式 有时候两个组件也需要通信(非父子关系).在简单的场景下,可以使用一个空的 Vue 实例作为中央事件总线. 本质是通过派发事件然后监听事件从而更改值,(父子组件通信也可用这个方式,但是不同的一点就是父子组件通信的时候可以不用一个空的Vue实例来做中转,这种方式我这里就不做演示的了,因为我的题目是非父子通信) 空的Vue实例 bus import Vue from 'vue' const bus = new Vue() export default bu

随机推荐