zoukankan      html  css  js  c++  java
  • vue-组件间通信

    抽个小空,写个总结。方便以后查看

    有不对的,请指出,非常感谢;

    1.父子组件通信

    1.   父组件 =》子组件
      1. props

            在父组件中:

              调用子组件的时候,将msg传递 可以是变量 用:

    <tips :msg="msg"></tips>
    

      

            在子组件中:

            通过props接受父组件传递过来的数据 :msg

    //template代码
     <div class="myalert">
        {{msg}}
        <a class="close" @click="closeFn">确定</a>
      </div>
    //js代码
    props:{
            msg:{require:true}
      },
    

      

           2.refs

            父组件中:

     用ref标记子组件
    <test msg="测试数据" ref="test"></test>
    js代码  通过$refs找到子组件 实例 并调用子组件的方法,并传参
    this.$refs.test.showFn('test');
    

            子组件中:

     子组件的定义的方法
    showFn(msg){
         this.showFlag=true;
         this.msg=msg
       }
    

      

        2.  子组件 =》父组件

            $emit 调用父组件中的方法,并传参

              父组件中:

    template代码 将父组件中的changeShowTips 方法传入
    <tips
          :msg="msg"
          @changeShowTips="changeShowTips"
          v-show="showTipsFlag"
        ></tips>
    js代码
    changeShowTips(data) {
          this.showTipsFlag = data;
        },
    

             子组件中:

     <div class="myalert">
        {{msg}}
        <a class="close" @click="closeFn">确定</a>
      </div>
    js调用 子组件中 利用$emit调用父组件中的方法,并传参
    closeFn(){
         this.$emit('changeShowTips',false);
       }
    

     

    2.兄弟组件

     结构: tips和test共同在一个父组件中

    在父组件中:定了一个一个fn函数 ,但是fn的处理函数是在$on之后的函数 这里写不管用

     fn() {},
    

      

    在tips.vue中

    在mounted 或者其他生命周期函数中,或者事件中 让父组件监听了fn这个函数 后面是他的处理函数 就可以接收到 兄弟组件 通过this.parent.$emit(fn)传来的值

      //这是兄弟组件触发事件以后的处理函数

     this.$parent.$on("fn", function(msg) {
            this.msg = msg;  
    这里的msg是兄弟组件传来的值
          });
    

      

     test.vue中  有一个可以改变tips组件数据的方法 ,其原理就是通过父组件调用改变方法

    changTipsFn() {
          this.$parent.$emit("fn", "123");
        }
    

      原理就是 父组件 动态监听了 一个函数fn的调用,当组件a调用了这个fn,则父组件拿到fn的值,并进行处理(改变了组件b的内容),只不过这个过程 父组件并没有直接参与,而是两个子组件,通过this.$parent来实现;

         也可以用this.$root实现

    3.祖先和后代

    1.  祖先 =》后代

      provide / inject 需要一起使用,允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效

    provide   Object | () => Object
    inject    Array<string> | { [key: string]: string | Symbol | Object } 一个字符串数组,或 一个对象,对象的 key 是本地的绑定名
    provide 和 inject 主要在开发高阶插件/组件库时使用。并不推荐用于普通应用程序代码中。

    父组件:
    provide() {
        return {
          common: { my_data: this.obj }
    // 提示:provide 和 inject 绑定并不是可响应的。是刻意为之的。如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。这里的obj就是父组件中定义的可响应的数据
        };
      },
    

      子组件:

    inject: {
        common: {
          default: () => {
            return {my_data: '0'}
          }
        }
      },
    
    使用:
     {{ common.my_data.title }}
      
      2.后代 =》祖先

         原理:递归查找父组件 通过$emit和$on进行传值

    // 定义一个dispatch方法,指定要派发事件名称和数据 
    function dispatch(eventName, data) {    let parent = this.$parent   
     // 只要还存在父元素就继续往上查找    
    while (parent) {        
      // 父元素用$emit触发        
      parent.$emit(eventName,data)       
       // 递归查找父元素        
      parent = parent.$parent    
      } }
     调用:
    // child.vue  子组件嗲用dispatch hello 方法是父组件的 
    <h1 @click="dispatch('hello', 'hello,world')">{{ msg }}</h1>
     
     // parent.vue
     this.$on('hello', this.sayHello)
     mounted() {
      // 父组件中监听hello,执行相应的this.sayHello方法 从而试得父组件接收到子组件的数据
        this.$on("hello", this.sayHello);
      },
        sayHello(msg) {
          alert(msg);
        },
        hello(msg) {
          console.log(msg + "触发了父元素的事件"); 并没有打印
        }
    

      

    每一级的parent我都打印了 

     

       一般不会这样做

    4.任意组件

    1. vuex
    2. 事件总线:vue-bus 创建一个Bus类父组事件派发,监听和回调管理

     事件总线:

    原理:

    在bus这个vue对象中注册foo事件,根据emit源码遍历执行所有名为foo的事件。当我们在b组件emit 分发事件后再a组件注册事件就将被执行 cbs[i].apply(vm, args);,再a组件的参数就将赋值给a组件中的data,根据vue数据绑定原理 此时this.bus的set()方法被触发,遍历bus属性在get()方法中收集到的依赖,并更新依赖,此时数据就从一个vue对象传递到另一个vue对象

     1. 在assets中创建一个bus.js

    import Vue from 'vue'
    export default new Vue;
    

      在需要的组件中引入

    import bus from "../assets/bus";
    

      事件触发

     bus.$emit("foo");
    此处 foo 是自定义名称,并没有实际作用;确保需要响应变化的组件 通过监听同名字 从而达到变化的效果
    

      需要同步做出改变的组件

      mounted() {
        bus.$on("foo", function() {
          console.log("监听到了bus");
        });
      },
    监听foo 变化 组件a触发了foo ,组件b监听到foo,从而做出改变 完成任意组件间通信
    
    需要通信的组件都需要引入bus
    

     2. 手写bus 非通过vue实例的

    // Bus:事件派发、监听和回调管理 
    class Bus {
      constructor() {
    
        //{
          //   eventName1:[fn1,fn2],    
          //   eventName2:[fn3,fn4],    
          //
        //}
        this.callbacks = {}
      }
      $on(name, fn) {
        this.callbacks[name] = this.callbacks[name] || [] this.callbacks[name].push(fn)
      }
      $emit(name, args) {
        if (this.callbacks[name]) {
          this.callbacks[name].forEach(cb => cb(args))
        }
      }
    }
    
    // main.js 
    Vue.prototype.$bus = new Bus()
    
    // child1 
    this.$bus.$on('foo', handle) // child2 this.$bus.$emit('foo')
    

       

      补充知识点:

        vm.$emit( event, arg ) //触发当前实例上的事件

        vm.$on( event, fn );//监听event事件后运行 fn; 

  • 相关阅读:
    深入理解npm run命令,run命令的两条潜规则
    oracle 删除表空间及数据文件方法
    Oracle11g创建表空间和用户,并授权
    java poi 读取excel 获取第一个不隐藏的sheet
    VBS 学习
    VBS 操作Excel
    Selenium + Python操作IE 速度很慢的解决办法
    Selenium打开IE报错“Protected Mode settings...”解决方法
    Robot Framework搭建
    获取一组元素的最后一个
  • 原文地址:https://www.cnblogs.com/GoTing/p/13598745.html
Copyright © 2011-2022 走看看