Moon系列之component、on、off、emit

前言

上篇文章分析了Methods、Computed以及Moon中双向绑定的处理,本篇文章主要分析下自定义组件以及Moon内置的指令的实现。

具体分析

还是通过一个简单的实例来进行分析,实例代码如下:

  <div id="app">
    <mn-test></mn-test>
  </div>
  <script src="./moon.js"></script>
  <script>
    Moon.component('mn-test', {
      template: '<p>{{msg}}</p>',
      data: {
        msg: 'hello world'
      }
    });
    new Moon({
      el: '#app'
    });
  </script>

Moon.component
Moon中提供了component来实现自定义组件,它是Moon构造函数的方法,可以直接使用,下面就来看看component是如何实现的:

  Moon.component = function (name, opts) {
      // 此处this代表Moon构造函数
      var Parent = this;
      // 是否存在name属性
      if (opts.name) {
        name = opts.name;
      } else {
        opts.name = name;
      }
	  // MoonComponent构造函数,可以看出实际上是调用Moon构造函数
      function MoonComponent() {
        Moon.call(this, opts);
      }
      // 设置MoonComponent构造函数的原型对象是Moon函数的原型对象,即MoonComponennt继承Moon
      MoonComponent.prototype = Object.create(Parent.prototype);
      MoonComponent.prototype.constructor = MoonComponent;
      // 重定义init方法
      MoonComponent.prototype.init = function () {
        callHook(this, 'init');
        this.$destroyed = false;
        this.$props = this.$opts.props || [];
   
	   // 模板html
        this.$template = this.$opts.template;
	   // 构建render函数生成html
        if (this.$render === noop) {
          this.$render = Moon.compile(this.$template);
        }
      };
      // 在全局对象components中注册
      components[name] = {
        CTor: MoonComponent,
        opts: opts
      };
      return MoonComponent;
    };

从上面可以看出,如下几点:

  • Moon.component实际上内部还是调用Moon构造函数
  • Moon.component内部继承了Moon.prototype
  • Moon.component内部重写了init方法

事件分发机制
Moon中也定义了Vue.js中事件分发机制(组件通信方式):on、off、emit,下面就具体来分析下它们内部的实现思想:

  • on
   // 事件注册
   Moon.prototype.on = function (eventName, handler) {
      var handlers = this.$events[eventName];
      // 从处理逻辑可知支持多个回调函数
      if (handlers === undefined) {
        this.$events[eventName] = [handler];
      } else {
        handlers.push(handler);
      }
    };
  • emit
  // 使用形式:Moon实例.emit(事件名,参数对象)
  Moon.prototype.emit = function (eventName, customMeta) {
      var meta = customMeta || {};
      meta.type = eventName;
      // 获取指定事件的处理的回调函数
      var handlers = this.$events[eventName];
      var globalHandlers = this.$events["*"];
      // 回调函数调用
      for (var i = 0; i < handlers.length; i++) {
        handlers[i](meta);
      }
      // 所有事件的回调函数
      if (globalHandlers !== undefined) {
        for (var i = 0; i < globalHandlers.length; i++) {
          globalHandlers[i](meta);
        }
      }
    };
    
  • off
    Moon.prototype.off = function (eventName, handler) {
      // 支持off()、off(事件)等3种形式
      if (eventName === undefined) {
        this.$events = {};
      } else if (handler === undefined) {
        this.$events[eventName] = [];
      } else {
        var handlers = this.$events[eventName];
        var index = handlers.indexOf(handler);
        handlers.splice(index, 1);
      }
    };
总结

Moon是非常值得一读的开源框架,它实现了类似Vue.js的功能,可以将其看成Vue.js的简化版,需要注意的是Moon的双向绑定与Vue.js实现的双向绑定还是存在一定区别。
之后的文章的大概顺序是:

  1. 虚拟DOM相关
  2. 指令以及slot相关
  3. monx相关
  4. moon-router相关
  5. moon-cli相关
  6. moon项目(moon-cli + monx+moon-router)整体分析
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Vue中,$on、$off、$emit是一些用于组件间通信的方法。可以通过使用$bus实例来传递非父子组件之间的数据。比如,使用$emit方法发送事件,使用$on方法监听事件,使用$off方法移除事件的绑定。 在子组件中,可以通过this.$bus.$emit(eventName, payload)来触发一个事件并传递数据。比如子组件1可以使用this.$bus.$emit("hello", param)来触发名为"hello"的事件,并将param作为数据传递。 在组件中,可以使用this.$bus.$on(eventName, callback)来监听一个事件。当触发了该事件时,绑定的回调函数将被调用。比如在子组件中可以使用this.$on('closeModal', res => {})来监听名为"closeModal"的事件。 同时,也可以使用this.$bus.$off(eventName)来移除绑定的事件。比如在组件销毁前,可以使用this.$off("closeModal")来移除对"closeModal"事件的监听。 通过使用$on、$off、$emit这些方法,可以方便地在Vue组件间进行通信和数据传递。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [vue中$bus的用法及$emit、$on、$off的使用](https://blog.csdn.net/leijie0322/article/details/128210817)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [vue中$emit跟$on,$off跟用法](https://blog.csdn.net/Billow_lamb/article/details/115007731)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [$emit,$on,$off--vue](https://blog.csdn.net/weixin_57844432/article/details/126599659)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值