mitt tiny-emitter发布订阅应用场景源码解析

mitt tiny-emitter发布订阅应用场景源码解析

简介

mitt是一个基于JavaScript的简单、快速、可扩展的发布/订阅(pub/sub)库,适用于各种应用场景。它的基本思想是订阅者向一个发布者注册其感兴趣的事件类型,当该类型事件发生时,订阅者会被通知并执行其所定义的响应逻辑。这种解耦合的模式为开发者提供了良好的可维护性和扩展性。

mitt的实现采用了只有500多个字节的精简代码,同时它还具有优雅和易用的API,因此备受广大开发者的喜爱。本文将对mitt的应用场景和源码进行详细介绍,并通过两个具体示例进行说明。

应用场景

mitt适用于各种应用场景,主要包括以下几个方面:

  • 事件代理:mitt可以用于事件代理,即将子组件通知/通信的事件发送到它们的父组件。这样可以很好地解耦,方便组件系统的维护和扩展。
  • 状态管理:mitt可以用于状态管理,即当状态改变时,它可以通知所有与之相关的订阅者,从而实现组件之间的协作、同步和响应。
  • 异步/回调处理:mitt可以用于异步/回调处理,即在异步/回调方法中使用mitt来处理完成事件,从而在异步操作完成后进行相应的处理。

源码解析

下面是mitt的源码解析。首先是mitt的主体代码:

export default function mitt(all = Object.create(null)) {
  return {
    /**
     * Register an event handler for the given type.
     *
     * @param  {string} type    Type of the event to listen for, or `"*"` for all events
     * @param  {Function} handler Function to call in response to the given event
     * @memberOf mitt
     */
    on(type, handler) {
      (all[type] || (all[type] = [])).push(handler);
    },

    /**
     * Remove an event handler for the given type.
     *
     * @param  {string} type    Type of the event to unregister `handler` from, or `"*"`
     * @param  {Function} handler Handler function to remove
     * @memberOf mitt
     */
    off(type, handler) {
      if (all[type]) {
        all[type].splice(all[type].indexOf(handler) >>> 0, 1);
      }
    },

    /**
     * Invoke all handlers for the given type.
     * If present, `"*"` handlers are invoked after type-matched handlers.
     *
     * @param {string} type The event type to invoke
     * @param {Any} [evt] Any value (object is recommended and powerful), passed to each handler
     * @memberOf mitt
     */
    emit(type, evt) {
      (all[type] || []).slice().map((handler) => { handler(evt); });
      (all['*'] || []).slice().map((handler) => { handler(type, evt); });
    }
  };
}

mitt函数接收一个名为all的对象作为参数,它用来存储事件类型和其对应的处理函数。具体的实现中,all使用Object.create(null)生成,它是一个全新的、空的对象,没有原型链的干扰。

mitt函数返回一个带有3个方法的对象,分别为onoffemit

  • on(type, handler):用于为指定类型的事件注册一个处理函数。
  • off(type, handler):用于删除指定类型的事件的处理函数。
  • emit(type, evt):用于触发指定类型的事件,并可传递相关数据。

下面是对每个方法的具体实现进行说明:

on(type, handler)

这个方法用于注册事件处理函数。它接收两个参数,分别为事件类型和处理函数。如果事件类型已经存在,则在其对应的处理函数数组中添加新处理函数;如果事件类型不存在,则创建新的处理函数数组,添加处理函数并保存至all对象中。代码如下:

(all[type] || (all[type] = [])).push(handler);

要注意的是,这里有一个判断条件(all[type] || (all[type] = [])),如果all对象没有type属性,那么就会将其初始化为一个空数组。

off(type, handler)

这个方法用于删除事件处理函数。它接收两个参数,分别为事件类型和处理函数。如果事件类型的处理函数数组存在,且其中包含指定的处理函数,则将其从数组中删除。代码如下:

if (all[type]) {
  all[type].splice(all[type].indexOf(handler) >>> 0, 1);
}

要注意的是,这里使用了位运算符>>>,它的作用是将其后面的数字转换为无符号32位整数。如果不使用位运算符,则在处理器函数未找到时,其返回值为-1,会导致数组删除失效。

emit(type, evt)

这个方法用于触发指定类型的事件。它接收两个参数,分别为事件类型和传递给事件处理函数的数据。首先,它将all对象中记录的该事件类型的所有处理函数复制到一个新数组中,然后依次执行每一个数组元素的处理函数。代码如下:

(all[type] || []).slice().map((handler) => { handler(evt); });

其次,如果存在all对象的'*'属性,则将包含在'*'中的处理函数也添加到新数组中。代码如下:

(all['*'] || []).slice().map((handler) => { handler(type, evt); });

这样,所有处理函数都将被执行,而且'*'中的处理函数将排在普通类型处理函数的后面。

示例说明

示例1:组件通信

Vue组件中使用mitt实现子组件向父组件通信。

<template>
  <div>
    <Child @notify="onNotify"></Child>
    <p v-if="message">{{ message }}</p>
  </div>
</template>

<script>
import mitt from 'mitt';
const emitter = mitt();

export default {
  data() {
    return {
      message: ''
    };
  },
  methods: {
    onNotify(data) {
      this.message = data;
    }
  },
  mounted() {
    emitter.on('notify', this.onNotify);
  },
  beforeDestroy() {
    emitter.off('notify', this.onNotify);
  }
};
</script>

在子组件中,我们可以通过emitter.emit('notify', data)将数据传递到父组件中。

<template>
  <button @click="onClick">点击通知</button>
</template>

<script>
import mitt from 'mitt';
const emitter = mitt();

export default {
  methods: {
    onClick() {
      // 通知父组件
      emitter.emit('notify', 'Hello, Parent Component!');
    }
  }
};
</script>

示例2:异步回调处理

通过mitt来处理异步方法的回调,例如Vue官方提供的$http方法。

// 使用Vue
this.$http.get('api/data').then((res) => {
  emitter.emit('data', res.data);
});

// 注册处理函数
emitter.on('data', (data) => {
  // 处理数据
});

或者使用其他HTTP库。

// 使用axios
axios.get('api/data').then((res) => {
  emitter.emit('data', res.data);
});

// 注册处理函数
emitter.on('data', (data) => {
  // 处理数据
});

这样,在异步操作完成后,我们就可以通过emit方法同步数据,实现逻辑的处理。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:mitt tiny-emitter发布订阅应用场景源码解析 - Python技术站

(0)
上一篇 2023年5月28日
下一篇 2023年5月28日

相关文章

  • Vue项目中常用的工具函数总结

    下面是“Vue项目中常用的工具函数总结”的攻略: Vue项目中常用的工具函数总结 什么是工具函数 在Vue项目中,我们会经常用到一些通用的、可重复使用的代码片段,这些代码片段被封装成了函数,我们称之为工具函数。通过使用这些函数,我们可以简化代码、提高开发效率、减少出错几率。 常用的工具函数 1.深度复制对象 在Vue项目中,我们经常需要将对象进行深度复制(也…

    Vue 2023年5月27日
    00
  • 详解auto-vue-file:一个自动创建vue组件的包

    下面是详细讲解 “详解auto-vue-file:一个自动创建vue组件的包” 的完整攻略: 什么是auto-vue-file auto-vue-file是一个自动创建Vue组件文件的Node.js包。使用auto-vue-file,你可以快速地创建Vue组件文件,省去手动创建文件的繁琐步骤。 安装auto-vue-file 要安装auto-vue-file…

    Vue 2023年5月28日
    00
  • Vue数据驱动模拟实现3

    Vue数据驱动模拟实现是指通过手动实现Vue框架底层的部分功能,来深入理解Vue的数据响应式原理。下面我们将给出实现Vue数据驱动的完整攻略: 1. 实现数据响应式 Vue的数据响应式是基于Object.defineProperties实现的,我们可以手动实现一个简化版的数据响应式: function defineReactive(obj, key, val…

    Vue 2023年5月28日
    00
  • vue中如何进行异步请求

    当在Vue.js应用程序中进行异步请求时,Vue.js使我们能够使用它在“vue-resource”和“axios”两个包中提供的两种不同方式。这两种方式都可以很容易地在Vue.js中创建和使用XHR请求。现在,我们来看一下如何使用这两种方式进行异步请求。 使用vue-resource进行异步请求 步骤一:安装vue-resource 在Vue.js项目中使…

    Vue 2023年5月29日
    00
  • 浅谈vue-props的default写不写有什么区别

    让我来详细讲解一下”浅谈vue-props的default写不写有什么区别”。 什么是vue-props? 在Vue.js框架中,组件是一个可复用、可包含任意代码的模块。每个组件往往都有自己的属性或状态,这些属性或状态需要传递给子组件或父组件,这就是props的作用。 Vue中的props属性类似于React.js组件中的props属性,用于接收外部传递的数…

    Vue 2023年5月28日
    00
  • vue中计算属性和方法的区别及说明

    Vue中计算属性和方法是两种常用的方式来处理数据的操作和计算。它们有不同的特点和用途,下面就具体说一下它们在使用中的区别及说明。 计算属性 计算属性是Vue中用于动态计算和返回结果的属性。计算属性会根据响应式数据的变化自动更新计算结果。计算属性有以下几个特点: 计算属性会缓存计算结果,只有在响应式数据发生变化时才会重新计算。这种缓存主要是为了避免重复计算和提…

    Vue 2023年5月27日
    00
  • Vue应用部署到服务器的正确方式

    Vue.js是一款功能强大但体积较小的前端框架,随着越来越多的Web应用程序采用Vue.js开发,部署Vue应用到服务器也变得越来越重要。以下是Vue应用部署到服务器的正确方式的详细攻略: 准备工作 首先,你需要确保你具备以下准备工作: Node.js环境:Vue.js需要Node.js来运行,因此请先安装Node.js。安装方式可以到Node.js官网上查…

    Vue 2023年5月27日
    00
  • VueJs路由跳转——vue-router的使用详解

    Vuejs路由跳转——vue-router的使用详解 Vuejs是一个非常优秀的前端框架,通过使用vue-router插件可以帮助我们轻松地实现单页应用SPA(Single-Page Application).本篇攻略将详细介绍Vuejs的路由使用。 Vue-router是什么? vue-router是Vue.js官方的路由插件。它可以轻松的帮助我们实现页面…

    Vue 2023年5月28日
    00
合作推广
合作推广
分享本页
返回顶部