zoukankan      html  css  js  c++  java
  • vue中的$on,$emit,$once,$off源码实现

    vue中的$on,$emit,$once,$off源码实现

    这几种模式是基于订阅观察者模式的,维护一个事件中心,on的时候将事件按名称存在事件中心里,称之为订阅者,然后emit将对应的事件进行发布,去执行事件中心里的对应的监听器。

    第一步就是创建一个构造构造,维护一个事件中心events

    1.  
      function EventEmiter(){
    2.  
      this.events = {}
    3.  
      }
    4.  
       

    $on

    1.  
      //event可以是事件名数组
    2.  
      EventEmiter.prototype.on = function(event,cb){
    3.  
      //多个事件
    4.  
      if(event instanceof Array){
    5.  
      event.forEach(fn=>this.on(fn,cb))
    6.  
      }
    7.  
      //单个事件
    8.  
      if(this.events[event]){
    9.  
      this.events[event].push(cb)
    10.  
      }else{
    11.  
      this.events[event] = [cb]
    12.  
      }
    13.  
      }
    14.  
       

    $emit

    1.  
      //cb 参数:单个事件名,args参数 this.emit('evt',a,b,c)
    2.  
      EventEmiter.prototype.emit = function(event){
    3.  
      let args = Array.from(arguments).slice(1)
    4.  
      let cbs = this.events[event];
    5.  
      if(cbs){
    6.  
      cbs.forEach(cb=>cb.apply(this,args))
    7.  
      }
    8.  
      }
    9.  
       

    $once

    1.  
      // 事件回调执行一次就清除事件,参数:单个事件名,单个监听器
    2.  
      EventEmiter.prototype.once = function(event,cb){
    3.  
      function oneTime(){
                    //先执行回调,然后清除该事件的对应回调
    4.  
      cb.apply(this,arguments)
    5.  
      this.off(event,cb)
    6.  
      }
      //on函数的fn属性添加一个标记,cb,方便循环off清除(提供了事件与回调的时候)
    7.  
      oneTime.cbName = cb;
    8.  
      this.on(event,oneTime);
    9.  
      }
    10.  
       

    $off

    1.  
      /*移除自定义事件监听器。
    2.  
      如果没有提供参数,则移除所有的事件监听器;
    3.  
      如果只提供了事件,则移除该事件所有的监听器;
    4.  
      如果同时提供了事件与回调,则只移除这个回调的监听器。
    5.  
      */
    6.  
      EventEmiter.prototype.off = function(event,cb){
    7.  
      if(!arguments){
    8.  
      this.events = Object.create(null)
    9.  
      }
    10.  
      if(event instanceof Array){
    11.  
      event.forEach(evt=>this.off(evt,cb))
    12.  
      }
    13.  
      if(!cb){
    14.  
      this.events[event] = null
    15.  
      }
    16.  
      if(cb){
    17.  
      let cbs = this.events[event]
    18.  
      if(cbs){
    19.  
      for(let i = 0;i<cbs.length;i++){
    20.  
      if(cb === cbs[i] || cb === cbs[i].cbName){
    21.  
      cbs.splice(i,1)
    22.  
      break
    23.  
      }
    24.  
      }
    25.  
      }
    26.  
      }
    27.  
      }
    28.  
       

    总结:其实原理非常简单,要注意的是$once 不是直接$on提交对应的回调函数,而是包装成另外的On函数,On函数作为回调Push进事件中心。On函数本身的作用是执行一次事件的回调,然后就立马$off去出该事件的监听回调。同时,On函数已经不是原来的cb回调了,所以为了待会$off的时候能准确找到背后的那个cb,所以给On函数添加了属性方便找到它

  • 相关阅读:
    How To Change Database Name
    Oracle备份与恢复案例
    Linux 下安装 Oracle9i
    在 Linux x86 上安装 Oracle 数据库 10g_1
    在 Linux x86 上安装 Oracle 数据库 10g_2
    Oracle9i数据库DataGuard实施及维护手册2
    在 Linux x86 上安装 Oracle 数据库 10g_3
    流程企业(钢铁企业)的制造执行系统
    理解和使用Oracle分析工具LogMiner
    Oracle9i数据库Data Guard实施及维护手册 1
  • 原文地址:https://www.cnblogs.com/fs0196/p/12965582.html
Copyright © 2011-2022 走看看