zoukankan      html  css  js  c++  java
  • vue第九单元(非父子通信 events 单向数据流)

    第九单元(非父子通信 events 单向数据流)

    #课程目标

    1. 了解非父子组件通信的原理,熟练实现非父子组件间的通信(重点)
    2. 了解单向数据流的含义,并且明白单向数据流的好处

    #知识点

    #1.非父子组件间的通信

    ​ 在昨天我们已经学习了父子间通信,子父间通信的实现方式,那么如果两个组件不是父子组件那么如何通信呢?

    思考 Vue 中非父子组件通信的方法有哪些?

    ​ 常用的方法有 EventBus 和 Vuex(这里暂时先不讲vuex,之后章节将会单独讲解)

    ​ 那么我们通过EventBus来实现通信,这个EventBus是什么呢?

    所谓EventBus就是创建一个事件中心,相当于中转站,可以用它来传递事件和接收事件。

    更加具体的说法,通过实例化一个Vue对象( 比如bus = new Vue() )作为母线,在组件中通过事件将参数传递出去( bus.$emit(event, [...args]) ),然后在其他组件中再通过bus( 这里按照刚前面实例化Vue对象后的叫法 )来监听此事件并接受参数( bus.$on(event, callback) )

    PS: 共用同一个Vue的实例( new Vue() ),通过此实例进行事件传递参数,在其他组件中监听此事件并且接收参数实现通信。

    接下来将详细的讲解这个bus是如何通信的:

    ​ 假设我们在根组件$root中有两个兄弟组件,分别为A.vueB.vue,如果我们在A.vue有一个数据msg想要传递给B.vue

    那么我们应该如何实现呢?

    第一步:在根组件中实现实例化一个空的Vue对象,放到根组件中的data中。

    import Vue from 'vue'
    import App from './App'
    import router from './router'
    //实例化的空Vue对象
    var bus = new Vue();
    
    Vue.config.productionTip = false
    
    /* eslint-disable no-new */
    new Vue({
      el: '#app',
      router,
      render: h => h(App),
      //把bus放到根组件中的data中
      data:{
      	bus:bus
      }
    })
    
     

    那么这个时候,在任何子组件中通过this.$root.bus都能够访问到。

    第二步:创建两个子组件,分别为Aa.vueBb.vue放到根组件中。

    //这里是根组件
    <template>
      <div>
      	<Aa></Aa>
      	<Bb></Bb>
      </div>
    </template>
    <script>
    import Aa from '@/components/A'
    import Bb from '@/components/B'
    export default {
      name: 'Ro',
      data () {
        return {
        	msg:'我是Ro'
        }
      },
      mounted(){
        ////此处已经拿到了根组件中bus实例
      	console.log(this.$root.bus)
      },
      components:{
      	Aa,Bb
      }
    }
    </script>
    
     

    第三步:想要Aa.vue传递数据给Bb.vue,那么就应该在Aa.vue中触发this.$root.bus.$emit()把相应的数据传递出去。

    <template>
      <div>
      	{{msg}}
      	<button @click="clickeMe">点击传个123给B</button>
      </div>
    </template>
    
    <script>
    export default {
      name: 'A',
      data () {
        return {
        	msg:'我是A'
        }
      },
      methods:{
      	clickeMe(){
            //点击触发bus的$emit事件
      		this.$root.bus.$emit('sendmsg','123')
      	}
      },
      mounted(){
        //此处已经拿到了根组件中bus实例
      	console.log(this.$root.bus)
      },
      components:{}
    }
    </script>
    
     

    第四步:想要Bb.vueAa.vue,那么就应该在Bb.vue中监听this.$root.bus.$on()把相应的数据传拿到当前组件中。

    <template>
      <div>
      	{{msg}}
      	--
      	{{msg1}}
      </div>
    </template>
    <script>
    export default {
      name: 'B',
      data () {
        return {
        	msg:'我是B',
        	msg1:'我是B未改变的数据'
        }
      },
      mounted(){
        //此处已经拿到了根组件中bus实例
      	console.log(this.$root.bus)
        //此处监听Aa.vue传递过来的参数 并且赋值给当前组件的 msg1
      	this.$root.bus.$on('sendmsg',(data)=>{
      		this.msg1 = data;
      	})
      },
      beforeDestroy(){
        //在组件销毁时别忘了解除事件绑定
      	this.$root.bus.$on('sendmsg');
      }
    }
    </script>
    
     

    这样就可以了,是不是很简单?

    如果有多个组件组件需要通信,是不是要在根组件上多建几个bus

    这个当然不需要的,只要保证事件名(eventName)不一样就行了。

    为什么要弄个 bus?直接this.$root.$onthis.$root.$emit不更简单粗暴?

    因为专门用一个空的 Vue 实例(bus)来做中央事件总线更加清晰也易于管理。

    #2.单向数据流

    为什么是单向数据流?

    所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。

    额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。

    这里有两种常见的试图改变一个 prop 的情形:

    1. 这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用。在这种情况下,最好定义一个本地的 data 属性并将这个 prop 用作其初始值:

      props: ['initialCounter'],
      data: function () {
        return {
          counter: this.initialCounter
        }
      }
      
       
    2. 这个 prop 以一种原始的值传入且需要进行转换。在这种情况下,最好使用这个 prop 的值来定义一个计算属性:

      props: ['size'],
      computed: {
        normalizedSize: function () {
          return this.size.trim().toLowerCase()
        }
      }
      
       

    #授课思路

    #案例和作业

    使用EventBus的非父子组件方式,实现两个兄弟组件间的数据双向绑定。

  • 相关阅读:
    python写的文件同步服务器
    从外部调用Django模块
    python监视线程池
    RabbitMQ手册翻译 RPC服务的例子
    python logging 模块完整使用示例
    使用内存磁盘加速linux
    About learning on the internet
    [转]伟大的程序员是怎样炼成的
    RabbitMQ手册翻译 Hello World的例子
    事半功倍:你应该知道的HTML5五大特性(转)
  • 原文地址:https://www.cnblogs.com/yzy521/p/14132031.html
Copyright © 2011-2022 走看看