vue组件间通信全面讲解

目录
  • 前言
  • 组件介绍
  • 一、父传子
    • 1. 父组件通过 props 传递数据给子组件
    • 2. 定义props的类型和默认值
  • 二、子传父
    • 子组件通过 $emit 传递数据给父组件
  • 三、非父子组件间数据传递
    • 1.通过公有的父组件进行非父子组件间的通信
    • 2. 通过使用一个空的 Vue 实例作为中央事件总线
  • 小结

前言

本章我们将介绍组件间是如何实现数据通信的。包括父组件向子组件、子组件向父组件、兄弟组件、非关系组件之间的数据通信。

组件通信是组件式开发中非常重要的一部分,也是组件式开发中的难点。

组件介绍

组件是 vue 最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用。

我们需要使用特定的方式来实现组件间的数据通信,接下来让我们一个个介绍这几种类别的组件通信是如何实现的。

一、父传子

1. 父组件通过 props 传递数据给子组件

父组件通过 props 属性向子组件传递数据。

子组件利用组件实例的 props 属性定义组件需要接收的参数,在使用组件时通过 attribute的方式传入参数。

// 在子组件内定义组件接收一个参数 name
{
  props: ['name']
}
// 父组件使用组件时传递参数 name
<child :name="name"></child>

接下来我们看一个具体示例:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <parent></parent>
  </div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type="text/javascript">
  Vue.component('parent', {
    template: '<child :name="name"></child>',
    data() {
      return {
        name: '句号'
      }
    }
  })
  Vue.component('child', {
    template: '<div>{{name}}</div>',
    props: ['name']
  })
  var vm = new Vue({
    el: '#app',
    data() {
    	return {}
    }
  })
</script>
</html>

代码解释

JS 代码第 14-18 行:定义了组件 child,并用 props 接收一个参数 name。

JS 代码第 4-12 行:定义了组件 parent,在组件中使用 <child></child> 引用组件,并用 attribute 的方式将 name 传递给组件 child。

在上面的例子中,组件 Child 接收参数 name,name 可以是字符串、数组、布尔值、对象等类型。但有时候我们需要给接收的参数指定一个特殊的类型和默认值,接下来我们就来介绍一下如何指定 props 的类型和默认值。

2. 定义props的类型和默认值

在上面的例子中,props 接收一个组件参数数组。

实际上,props 也可以接收一个对象,对象key为组件接收参数的参数名,其值是一个对象,属性 type 用来指定参数的类型,属性 default 用来指定参数的默认值:

{
  props: {
    name: {
      type: String,
      default: '句号'
    }
  }
}

接下来我们看一个具体示例:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <parent></parent>
  </div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type="text/javascript">
  Vue.component('parent', {
    template: '<div><child :name="name" /> <child/></div>',
    data() {
      return {
        name: '慕课网'
      }
    }
  })
  Vue.component('child', {
    template: '<div>{{name}}</div>',
    props: {
      name: {
        type: String,
        default: '句号'
      }
    }
  })
  var vm = new Vue({
    el: '#app',
    data() {
    	return {}
    }
  })
</script>
</html>

JS 代码第 11-19 行:定义了组件 child,并用 props 接收一个字符串类型的参数 name,其默认值是:句号。

JS 代码第 3-10 行:定义了组件 parent,在组件中使用<child></child>两次引用组件,<child :name="name" /> 的方式传递 name 值,<child/> 使用默认的 name 值。

TIPS: 注意,给数组和对象类型的 props设置默认值的时候,需要按照以下的写法:

props: {
  detail: {
    type: Object,
    default: () => {
      return {
        name: '句号'
      }
    }
  },
  loves: {
    type: Array,
    default: () => {
      return []
    }
  }
}

二、子传父

子组件通过 $emit 传递数据给父组件

介绍完父组件传递数据给子组件的方式,我们再来看看子组件是如何传递数据给父组件的。

子组件通过 $emit 传递事件给父组件,父组件通过$on监听事件:

// 子组件定义事件
this.$emit('事件名称', '传递的参数') //例: this.$emit('add', 111)

// 父组件监听事件的触发
<child  @事件名称="事件触发的方法"/>

具体示例:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <parent></parent>
  </div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type="text/javascript">
  Vue.component('parent', {
    template: '<div><child :name="name" :count="count" @add="add"/></div>',
    data() {
      return {
        name: '句号',
        count: 18
      }
    },
    methods: {
      // 父组件通过 @事件名 监听
      // count 表示事件触发传递的参数
      add(count) {
        this.count = count
      }
    }
  })
  Vue.component('child', {
    template: '<div>我是:{{name}}, 我今年 {{count}}岁。<button @click="add">加一岁</button></div>',
    props: {
      name: {
        type: String,
        default: '句号'
      },
      count: {
        type: Number,
        default: 18
      }
    },
    methods: {
      add(){
        // add -> 触发的事件名
        // this.count + 1 -> 触发事件时传递的参数
        this.$emit('add', this.count + 1)
      }
    }
  })
  var vm = new Vue({
    el: '#app',
    data() {
    	return {}
    }
  })
</script>
</html>

代码解释

JS 代码第 19-38 行:定义了组件 child,该组件接收两个参数:1. 字符串类型的 name,默认值为:句号。2. 数字类型的 age,默认值为 18。组件模版中,通过按钮点击事件触发 add 方法,该方法内部通过$emit触发事件 add,并将 age + 1 的值作为参数传递。

JS 代码第 3-18 行:定义了组件 parent,在组件中使用<child :name="name" :age="age" @add="add"/>引用组件,并绑定 add 事件,当事件 add 触发时调用 methods 中的 add 函数。

三、非父子组件间数据传递

前面我们介绍了具有父子关系的组件是如何进行数据传递的。但实际上,并不是所有的组件都是父子关系,组件间还有兄弟组件、子孙组件、无关系组件,那么这些组件间是如何进行通信的呢?

相信在学完本章前面的内容之后这个问题并不能难倒大家。

  • 对于兄弟组件的数据通信:它们有共同的父组件,我们可以通过父组件传递的方式实现数据通信。
  • 对于子孙组件的数据通信:可以通过 props 的方式向下逐层传递下去,也可以通过 $emit 将事件向上逐层传递。
  • 对于非关系组件的数据通信:通过使用一个空的Vue实例作为中央事件总线。

1.通过公有的父组件进行非父子组件间的通信

假设现在有三个组件分别是<Parent>、<ChildA>、<ChildB>,其中组件<Parent>是<ChildA>和<ChildB>的父组件,<ChildA>和<ChildB>为兄弟组件,<ChildA>和<ChildB>组件间的通信可以借助<Parent>来间接传递。它的流程大致是这样:

<ChildA>通过$emit将数据传递给<Parent>,<Parent>再通过props将数据传递给<ChildB> 。

具体示例:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <person @modify="modify"></person>
    <detail :name="name" :count="count"/>
  </div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type="text/javascript">
  Vue.component('person', {
    template: '<div><div>姓名:<input type="text" v-model="name"/></div><div>年龄:<input type="text" v-model="count"/></div><button @click="modify">修改</button></div>',
    data() {
      return {
        name: '句号',
        count: 18
      }
    },
    methods: {
      modify() {
        this.$emit('modify', {name: this.name, count: this.count})
      }
    }
  })
  Vue.component('detail', {
    template: '<div>我是:{{name}}, 我今年 {{count}}岁。</div>',
    props: {
      name: {
        type: String,
        default: '句号'
      },
      count: {
        type: Number,
        default: 18
      }
    },
    methods: {
    }
  })
  var vm = new Vue({
    el: '#app',
    data() {
    	return {
        name: '句号',
        count: 18
      }
    },
    methods: {
      modify(detail) {
        this.name = detail.name
        this.count = parseInt(detail.count)
      }
    }
  })
</script>
</html>

代码解释

JS 代码第 18-30 行:定义了组件 detail,它从父组件接收 name 和 age 两个参数。

JS 代码第 3-17 行:定义了组件 person,它通过 $emit 将组件内输入的 name 和 age 传递给父组件。

JS 代码第 38-41 行:接收了组件 person 传递过来的事件,并修改 name 和 age。

HTML 代码第 3 行:将 name 和 age 传递给组件 detail。

2. 通过使用一个空的 Vue 实例作为中央事件总线

在Vue中可以使用 EventBus 来作为沟通桥梁的概念,就像是所有组件共用相同的事件中心,可以向该中心注册发送事件或接收事件,所以组件都可以上下平行地通知其他组件。

首先我们需要做的是创建事件总线,并将它挂载到Vue原型上,在实例中通过this.bus.$emit发送事件,通过this.bus.$on接收事件

// 定义事件总线
let bus = new Vue()
Vue.prototype.bus = bus

// 定义发送事件
this.bus.$emit('事件名称', data)

// 定义接收事件 并在回调中接收参数
this.bus.$on('事件名称', (data) => {
})

接下来我们看一段具体示例代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <person></person>
    <detail />
  </div>
</body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script type="text/javascript">
  let bus = new Vue()
  Vue.prototype.bus = bus

  Vue.component('person', {
    template: '<div><div>姓名:<input type="text" v-model="name"/></div><div>年龄:<input type="text" v-model="count"/></div><button @click="modify">修改</button></div>',
    data() {
      return {
        name: '句号',
        count: 18
      }
    },
    methods: {
      modify() {
        this.bus.$emit('modify', {name: this.name, count: this.count})
      }
    }
  })
  Vue.component('detail', {
    template: '<div>我是:{{name}}, 我今年 {{count}}岁。</div>',
    data() {
    	return {
        name: '句号',
        count: 18
      }
    },
    mounted() {
      this.bus.$on('modify', (detail) => {
        this.name = detail.name
        this.count = detail.count
      })
    }
  })
  var vm = new Vue({
    el: '#app',
    methods: {
    }
  })
</script>
</html>

代码解释

JS 代码第 3-4 行:通过 new Vue() 创建一个 vue 实例,并将它挂载在 Vue 的原型上。这样,在 vue 组件中可以通过 this.bus 访问到这个实例对象。

JS 代码第 5-18 行:定义了组件 person,当点击修改按钮的时候通过 this.bus.$emit 发送一个名为 modify 的事件,并将组件内输入的 name 和 age 作为参数传递。

JS 代码第 19-33 行:定义组件 detail,在组件内部通过this.bus.$on监听名为 modify 的事件,当事件触发时执行修改操作。

小结

在本章,我们介绍了组件间的通信方式,主要有以下知识点:

  • 父组件通过 props 向子组件传递参数进行数据通信;
  • 子组件通过 $emit 向父组件传递事件进行数据通信;
  • 兄弟组件通过共同父组件进行数据通信;
  • 通过使用一个空的 Vue 实例作为中央事件总线进行非关系层组件的数据通信。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 老生常谈vue3组件通信方式

    目录 vue3七种组件通信方式 1. Props方式 2. emit方式 3. v-model方式 4.Refs 5. provide/inject 6. eventBus 7. vuex/pinia vue3七种组件通信方式 面试题经常会问到vue3组件间的通信方式,下文列举了七种常见的通信方式. props emit v-model refs provide/inject eventBus Vuex4/pinia(vuex5) 1. Props方式 父组件以数据绑定的形式声明要传递的数据,子

  • Vue组件间的通信方式详析

    目录 前言 组件之间通信的场景 父子组件之间的通信 父组件通过 prop 向子组件传递数据 子组件通过自定义事件向父组件传递数据 兄弟组件之间的通信 状态提升 隔代组件之间的通信 attrs/attrs/listeners provide/inject 基于 $parent/$children 实现的 dispatch 和 broadcast 前言 在Vue组件库开发过程中,Vue组件之间的通信一直是一个重要的话题,虽然官方推出的 Vuex 状态管理方案可以很好的解决组件之间的通信问题,但是在组

  • Vue2和Vue3的10种组件通信方式梳理

    目录 props emit attrs和listeners provide/inject parent/children expose&ref EventBus/mitt 写在最后 Vue中组件通信方式有很多,其中Vue2和Vue3实现起来也会有很多差异:本文将通过选项式API 组合式API以及setup三种不同实现方式全面介绍Vue2和Vue3的组件通信方式. 其中将要实现的通信方式如下表所示: 方式 Vue2 Vue3 父传子 props props 子传父 $emit emits 父传子

  • Vue组件之间的通信方式详细讲解

    目录 前言 一.父级传数据给子级 1.传输固定的具体数据 2.动态语法 3.子组件调用父组件 二.子级传数据给父级 1.使用自定义事件 2.$refs的使用 3.同级别组价以及任意组件之间的数据传递 前言 在前面,我们已经了解了vue的组件以及vue组件之间的层级关系,这个在博主的往期博客,感兴趣的可以往前挪,地址是: 1.vue组件 2.vue组件的层级关系 本文主要编写记录的是,组件之间的通信的模式以及通信的方式,我们的组件之间只能调用自己的属性和自己的方法,不能调用其他组件的属性以及方法,

  • Vue常见组件间通信方案及典型应用场景详解

    目录 什么是组件通信 1.父子组件通信场景 2.兄弟组件通信场景 3.根组件和后代组件通信场景 4.插槽通信场景 5 无直接关系的组件通信场景 6 大型项目中的复杂组件通信场景 - Vuex状态管理 7 其他的一些组件通信方案 总结 什么是组件通信 所谓组件通信,就是组件之间的数据交互,也就是把一个组件A里面的数据传递到另一个组件B,并能够让组件B根据这个数据更新界面. 在 Vue中,可用的通信方案有很多,下面给大家描述几个常用的组件通信方案及其典型的应用场景. 1.父子组件通信场景 父子组件通

  • Vue组件通信深入分析

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

  • vue组件间通信全面讲解

    目录 前言 组件介绍 一.父传子 1. 父组件通过 props 传递数据给子组件 2. 定义props的类型和默认值 二.子传父 子组件通过 $emit 传递数据给父组件 三.非父子组件间数据传递 1.通过公有的父组件进行非父子组件间的通信 2. 通过使用一个空的 Vue 实例作为中央事件总线 小结 前言 本章我们将介绍组件间是如何实现数据通信的.包括父组件向子组件.子组件向父组件.兄弟组件.非关系组件之间的数据通信. 组件通信是组件式开发中非常重要的一部分,也是组件式开发中的难点. 组件介绍

  • vue组件间通信六种方式(总结篇)

    前言 组件是 vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用.一般来说,组件可以有以下几种关系: 如上图所示,A 和 B.B 和 C.B 和 D 都是父子关系,C 和 D 是兄弟关系,A 和 C 是隔代关系(可能隔多代). 针对不同的使用场景,如何选择行之有效的通信方式?这是我们所要探讨的主题.本文总结了vue组件间通信的几种方式,如props. $emit / $on .vuex. $parent / $children . $attrs

  • Vue组件间通信 Vuex的用法解析

    上回说到Vue组件间通讯,最后留了一个彩蛋~~~Vuex.Vuex是另一种组件通讯的方法,这节来说说Vuex(store仓库). 首先Vuex需要安装,安装的方式有很多,在这里就不一一细说了.我是通过npm方式安装的: npm install vuex --save 安装好之后需要再main.js里全局引入: import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex)new Vue({el:'#app',store,components

  • 超详细的vue组件间通信总结

    目录 前言 一.props.$emit单向数据流 二.$parent.$children 三.$attrs.$listeners 四.provide.inject 五.eventBus(事件总线) 六.vuex 七.localstorage 总结 前言 组件通信在我们平时开发过程中,特别是在vue和在react中,有着举足轻重的地位.本篇将总结在vue中,组件之间通信的几种方式: props.$emit $parent.$children $attrs.$listeners provide.in

  • vue之父子组件间通信实例讲解(props、$ref、$emit)

    组件是 vue.js 最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用.那么组件间如何通信,也就成为了vue中重点知识了.这篇文章将会通过props.$ref和 $emit 这几个知识点,来讲解如何实现父子组件间通信. 在说如何实现通信之前,我们先来建两个组件father.vue和child.vue作为示例的基础. //父组件 <template> <div> <h1>我是父组件!</h1> <child>

  • vue组件间通信子与父详解(二)

    接着vue组件父与子通信详解继续学习. 二.组件间通信(子组件传值给父组件) 通过事件的方式来完成数据的传输. ①在父组件中 定义一个方法,用来接收子组件所通过事件传来的值 methods:{ recvMsg:function(msg){ //参数msg就是子组件通过事件出来的数据 } } ②绑定事件处理函数 事件一般情况 都是自定义事件 <child-component @myEvent="recvMsg"></child-component> ③在子组件触发

  • vue组件间通信解析

    组件间通信(父子,兄弟) 相关链接\组件通信:点击查看 学习链接:Vue.js--60分钟快速入门点击查看 分分钟玩转Vue.js组件点击查看 父组件传子组件 父传子方法(一) 属性传递 props //子组件 <template> <ul> <li v-for="item in dataList">{{item}}</li> </ul> </template> <script> export defa

  • Vue组件间通信方法总结(父子组件、兄弟组件及祖先后代组件间)

    前言 除了使用 Vuex 方法外,vue 提供了各种各样的组件间通信的方案.文章整理一下父子组件.兄弟组件.祖先后代组件间是如何通信的.

  • Vue 父子组件、组件间通信

    本人对Vue组件间通信不懂,搜索了很多关于Vue 父子组件间通信介绍,下面我来记录一下,有需要了解Vue 父子组件.组件间通信的朋友可参考.希望此文章对各位有所帮助. <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>组件</title> <meta name="viewport"

  • Vue如何实现组件间通信

    1. 父子间通信 最常见的就是父子之间的通信,通信是双向的数据传递. 1.1 父组件 --> 儿子组件 父组件向儿子组件传递数据的方式就是 通过 Prop 向子组件传递数据. //child.vue <template> <div> 我是儿子,我收到来自父亲的数据为 {{value}} </div> </template> <script> export default { props:{ value: String } } //App.v

随机推荐