zoukankan      html  css  js  c++  java
  • vue 兄弟组件是如何通信的

    今天面试被问到这个问题,我自己思考的是让父组件做两个子组件之间的桥梁,但是我并没有去说,感觉是有些low啊,面试完了赶紧查查是怎么通信的;

    就是我自己设想的这种方法也是解决问题的一种方法;

    兄弟组件通讯

    在Vue中实现兄弟组件的通讯也有几种方法,其中一种方法是让父组件允当两个子组件之间的中间件(中继);

    另一种就是使用EventBus(事件总线),它允许两个子组件之间直接通讯,而不需要涉及父组件。

    这里就要好好了解下EventBus(事件总线)的概念了;

    1、通过父组件进行兄弟组件之间通讯

    先来看第一个方法,就是让兄弟组件通过一个共同的父组件彼此通讯。

    我们还是通过示例来学习。接下来的这个示例包含父组件和两个子组件,这两个子组件是兄弟组件。单击兄弟组件上的按钮,可以看到他们之间可以相互通讯。

     

     首先创建ParentCard组件:

     1 <!-- ParentCard.vue -->
     2 
     3 <template>
     4 
     5   <div class="card">
     6 
     7     <div class="card-header">
     8 
     9       <h5 v-text="theCardTitle"></h5>
    10 
    11       <button @click="momSaidChill" v-if="stopFighting()" class="btn">停止通讯</button>
    12 
    13     </div>
    14 
    15     <div class="card-body">
    16 
    17       <brother-card :messageSon="messageson" @brotherSaid="messageDaughter($event)"></brother-card>
    18 
    19       <sister-card :messageDaughter="messagedaughter" @sisterSaid="messageSon($event)"></sister-card>
    20 
    21     </div>
    22 
    23   </div>
    24 
    25 </template>
    26 
    27 <script>
    28 
    29 import BrotherCard from './BrotherCard';
    30 
    31 import SisterCard from './SisterCard'
    32 
    33 export default {
    34 
    35   name: 'ParentCard',
    36 
    37   data: () => ({
    38 
    39     theCardTitle: '父组件',
    40 
    41     messagedaughter:'',
    42 
    43     messageson:''
    44 
    45   }),
    46 
    47   components: {
    48 
    49     BrotherCard,
    50 
    51     SisterCard
    52 
    53   },
    54 
    55   methods: {
    56 
    57     messageDaughter(message) {
    58 
    59       this.messagedaughter = message;
    60 
    61     },
    62 
    63     messageSon(message) {
    64 
    65       this.messageson = message;
    66 
    67     },
    68 
    69     stopFighting() {
    70 
    71       if (this.messagedaughter && this.messageson) {
    72 
    73         return true
    74 
    75       }
    76 
    77       return false
    78 
    79     },
    80 
    81     momSaidChill() {
    82 
    83       this.messagedaughter = '',
    84 
    85       this.messageson = ''
    86 
    87     }
    88 
    89   }
    90 
    91 }; 
    92 
    93 </script>

    创建SisterCard组件:

     1 <!-- SisterCard.vue -->
     2 
     3 <template>
     4 
     5   <div class="message">
     6 
     7     <div class="message-header">
     8 
     9       <h5 v-text="theCardTitle"></h5>
    10 
    11     </div>
    12 
    13     <div class="message-body">
    14 
    15       <p class="message-text">我是Sister组件</p>
    16 
    17       <button @click="messageBrother" class="btn">给哥哥发消息</button>
    18 
    19       <div v-if="messageDaughter" class="alert" v-html="messageDaughter"></div>
    20 
    21     </div>
    22 
    23   </div>
    24 
    25 </template>
    26 
    27 <script>
    28 
    29 export default {
    30 
    31   name: 'SisterCard',
    32 
    33   props: ['messageDaughter'],
    34 
    35   data: () => ({
    36 
    37     theCardTitle: '子组件2'
    38 
    39   }),
    40 
    41   methods: {
    42 
    43     messageBrother() {
    44 
    45       this.$emit('sisterSaid', '妈妈说,该做作业了!(^_^)!!!')
    46 
    47     }
    48 
    49   }
    50 
    51 }
    52 
    53 </script>

    接着创建BrotherCard组件:

     1 <!-- BrotherCard.vue -->
     2 
     3 <template>
     4 
     5   <div class="message">
     6 
     7     <div class="message-header">
     8 
     9       <h5 v-text="theCardTitle"></h5>
    10 
    11     </div>
    12 
    13     <div class="message-body">
    14 
    15       <p class="message-text">我是Brother组件</p>
    16 
    17       <button @click="messageSister" class="btn">给妹妹发消息</button>
    18 
    19       <div v-if="messageSon" class="alert" v-html="messageSon"></div>
    20 
    21     </div>
    22 
    23   </div>
    24 
    25 </template>
    26 
    27 <script>
    28 
    29 export default {
    30 
    31   name: 'BrotherCard',
    32 
    33   props: ['messageSon'],
    34 
    35   data: () => ({
    36 
    37     theCardTitle: '子组件1'
    38 
    39   }),
    40 
    41   methods: {
    42 
    43     messageSister() {
    44 
    45       this.$emit('brotherSaid', '妈妈说,该做作业了!(^_^)!!!')
    46 
    47     }
    48 
    49   }
    50 
    51 }
    52 
    53 </script>

    最终效果如下:

    接下来简单看看这个实现过程。

    SisterCard通过ParentCardBrotherCard通讯

    首先来看SisterCard是如何与BrotherCard通讯的。从示例中可以看出,他们两之间的通讯是通过其父组件ParentCard作为中间媒介来进行通讯的。

    我们在SisterCard组件的<template>中为messageBrother()方法设置了一个@click事件来监听该事件。

    <button @click="messageBrother" class="btn">给哥哥发消息</button>

    当用户点击SisterCard中的“给哥哥发消息”将会触发messageBrother()方法。在这个方法中,将发出一个sisterSaid事件,并且把妈妈说,该做作业了!(^_^)!!!信息发送出去。

    1 methods: {
    2 
    3   messageBrother() {
    4 
    5     this.$emit("sisterSaid", "妈妈说,该做作业了!(^_^)!!!");
    6 
    7   } 
    8 
    9 }

    ParentCard<template>中定制了一个@sisterSaid事件侦听器,它触发了messageSon()方法。所以父组件在这两个兄弟组件之间起到了传递的作用。

    <sister-card :messageDaughter="messagedaughter" @sisterSaid="messageSon($event)"></sister-card>

    另外在ParentCard组件中声明了messageSon()方法,该方法接受上面发送的自定义事件,并将其设置为messageson属性。

    这样一来,ParentCard组件中messageson就由空字符串变成了妈妈说,该做作业了!(^_^)!!!

    接着在ParentCard组件自定义标签<brother-card>通过:messageSon="messageson"的方式将messageson属性绑定到<brother-card>

    <brother-card :messageSon="messageson" @brotherSaid="messageDaughter($event)"></brother-card>

    这个时候在BrotherCard组件中设置props的属性值为messageSon。这样就可以访问源自于SisterCard组件的数据,并且该数据在BrotherCard中显示。

    props: ["messageSon"],

    最后在BrotherCard组件就可以使用该数据。我们可以通过v-if指令来查看messageSon是否有任何有用的数据,如果有,那么就在div.alert中显示该消息:

    <div v-if="messageSon" class="alert" v-html="messageSon"></div>

    上面的描述过程也适用于BrotherCard通过ParentCardSisterCard进行数据通讯。

    2、通过EventBus进行兄弟间组件通讯

    随着应用程序越来越庞大,通过父组件来传递所有内容会把事情变得越来越棘手。不过我们还有另一种选择,那就是使用EventBus架起兄弟之间通讯的桥梁。接下来看看我们是如何利用这一点一完成兄弟组件之间的数据通讯。

    我们同样基于上面的示例来做修改。接下来的示例中,ParentCard组件包含了SisterCardBrotherCard两个子组件,而且这两个子组件是兄弟组件。

    首先在main.js文件中定义一个新的eventBus对象,其实他是一个全新的Vue实例:

     1 // main.js
     2 
     3 import Vue from 'vue'
     4 
     5 import App from './App'
     6 
     7 export const eventBus = new Vue()
     8 
     9 new Vue({
    10 
    11   el: '#app',
    12 
    13   render: h => h(App)
    14 
    15 })

    接着在新创建的BrotherCard组件导入main.js

    1 <!-- BrotherCard.vue -->
    2 
    3 <script>
    4 
    5 import { eventBus } from '../main'
    6 
    7 </script>

    eventBus实例现在将成为BrotherCard组件中发出事件的实例。现在我们可以使用eventBus.$emit来替代上例中的this.$emiteventBus是一个Vue实例,而且eventBus有这个$emit方法,这就是我们能够这么用的原因。这样做同样会触发相同的自定义事件名称和消息。

    1 methods: {
    2 
    3   messageSister() {
    4 
    5     eventBus.$emit('brotherSaid', '妈妈说,该做作业了!(^_^)!!!')
    6 
    7   }
    8 
    9 } 

    同样可以在SisterCard组件中引入eventBus

    <script>

    import { eventBus } from '../main'

    </script>

    created()生命周期钩子添加到SisterCard组件。在created()钩子中添加eventBus启动自定义事件的侦听器。当使用SisterCard组件时,该侦听器将开始运行并且会保持运行。下面的代码只是侦听brotherSaid自定义事件,然后触发回调,将作为自定义事件有效负载传递的消息分配给fromBrother

    1 created() {
    2 
    3   eventBus.$on('brotherSaid', (message) => {
    4 
    5     this.fromBrother = message
    6 
    7   })
    8 
    9 } 

    这样就可以有条件地显示来自BrotherCard的信息:

    <div v-if="fromBrother" class="alert" v-html="fromBrother"></div>

    上面看到的是如何通过eventBus实现SisterCardBrotherCard传递数据的方式,反之,BrotherCard向SisterCard`传递数据也可以使用类似的方式。

    最终代码如下:

     1 <!-- SisterCard.vue -->
     2 
     3 <template>
     4 
     5   <div class="message">
     6 
     7     <div class="message-header">
     8 
     9       <h5 v-text="theCardTitle"></h5>
    10 
    11     </div>
    12 
    13     <div class="message-body">
    14 
    15       <p class="message-text">我是Sister组件</p>
    16 
    17       <button @click="messageBrother" class="btn">给哥哥发消息</button>
    18 
    19       <div v-if="fromBrother" class="alert" v-html="fromBrother"></div>
    20 
    21     </div>
    22 
    23   </div>
    24 
    25 </template>
    26 
    27 <script>
    28 
    29 import { eventBus } from "../main";
    30 
    31 export default {
    32 
    33   name: "SisterCard",
    34 
    35   data: () => ({
    36 
    37     theCardTitle: "Sister Card",
    38 
    39     fromBrother: ""
    40 
    41   }),
    42 
    43   methods: {
    44 
    45     messageBrother() {
    46 
    47       eventBus.$emit("sisterSaid", "妈妈说,该做作业了!(^_^)!!!");
    48 
    49     }
    50 
    51   },
    52 
    53   created() {
    54 
    55     eventBus.$on("brotherSaid", message => {
    56 
    57       this.fromBrother = message;
    58 
    59     });
    60 
    61   }
    62 
    63 };
    64 
    65 </script>
     1 <!-- BrotherCard.vue -->
     2 
     3 <template>
     4 
     5   <div class="message">
     6 
     7     <div class="message-header">
     8 
     9       <h5 v-text="theCardTitle"></h5>
    10 
    11     </div>
    12 
    13     <div class="message-body">
    14 
    15       <p class="message-text">我是Brother组件</p>
    16 
    17       <button @click="messageSister" class="btn">给妹妹发消息</button>
    18 
    19       <div v-if="fromSister" class="alert" v-html="fromSister"></div>
    20 
    21     </div>
    22 
    23   </div>
    24 
    25 </template>
    26 
    27 <script>
    28 
    29 import { eventBus } from "../main.js";
    30 
    31 export default {
    32 
    33   name: "BrotherCard",
    34 
    35   data: () => ({
    36 
    37     theCardTitle: "Brother Card",
    38 
    39     fromSister: ""
    40 
    41   }),
    42 
    43   methods: {
    44 
    45     messageSister() {
    46 
    47       eventBus.$emit("brotherSaid", "妈妈说,该做作业了!(^_^)!!!");
    48 
    49     }
    50 
    51   },
    52 
    53   created() {
    54 
    55     eventBus.$on("sisterSaid", message => {
    56 
    57       this.fromSister = message;
    58 
    59     });
    60 
    61   }
    62 
    63 };
    64 
    65 </script>

    最后创建的ParentCard组件,我们可以像下面这样编码:

     1 <!-- ParentCard -->
     2 
     3 <template>
     4 
     5   <div class="card">
     6 
     7     <div class="card-header">
     8 
     9       <h5 v-text="theCardTitle"></h5>
    10 
    11     </div>
    12 
    13     <div class="card-body">
    14 
    15       <brother-card></brother-card>
    16 
    17       <sister-card></sister-card>
    18 
    19     </div>
    20 
    21   </div>
    22 
    23 </template>
    24 
    25 <script>
    26 
    27 import BrotherCard from "./BrotherCard";
    28 
    29 import SisterCard from "./SisterCard";
    30 
    31 export default {
    32 
    33   name: "ParentCard",
    34 
    35   data: () => ({
    36 
    37     theCardTitle: "Parent Card"
    38 
    39   }),
    40 
    41   components: {
    42 
    43     BrotherCard,
    44 
    45     SisterCard
    46 
    47   }
    48 
    49 };
    50 
    51 </script>

    总结

    在本教程中,我们学习了在Vue中如何实现组件之间的通讯。通过实例看到了如何实现父组件向子组件,子组件向父组件以及兄弟组件间的数据通讯。简单的根据为:

    • 通过props可以实现父组件向子组件发送数据
    • 通过自定义事件可以实现子组件向父组件发送数据
    • 兄弟组件数据通讯除了借助共同的父组件做为通讯桥梁之外,还可以通过eventBus来让兄弟之间组件进行数据通讯

    最后用一张图来简单的描述一下:

    原文: https://www.w3cplus.com/vue/component-communication.html 

     ps:希望大家早日成为前端大神,哈哈哈

    
    
  • 相关阅读:
    Xcode 4.1~4.6 + iOS 5、iOS 6免证书(iDP)开发+真机调试+生成IPA全攻略
    Java程序员快速入门Go语言
    企业站常用的点击后弹出下拉菜单导航
    企业站常用漂亮横向导航菜单
    点击弹出弹性下拉菜单效果
    很酷的伸缩导航菜单效果,可自定义样式和菜单项。
    导航条点击按钮切换效果
    不错的二级导航菜单特效
    商城常用产品分类导航条
    css实现鼠标经过导航文字偏位效果
  • 原文地址:https://www.cnblogs.com/zhilu/p/13851827.html
Copyright © 2011-2022 走看看