创建2个可以相互通信的jquery插件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了创建2个可以相互通信的jquery插件相关的知识,希望对你有一定的参考价值。

我现在的头很乱。我想创建2个jquery插件:

  1. 一个标签插件
  2. 一个滑块插件。

此插件必须相互通信,例如,如果单击选项卡,此选项卡将激活相关滑块中的正确索引。如果我点击幻灯片,这也会激活正确的选项卡。

我开始为此创建事件监听器和触发器,当单击我的选项卡时,触发事件'tabChanged',并且在我的滑块插件中我正在收听它。但是这里有麻烦,我的滑块可以在我的标签之前加载,所以听众没有正确连接......

我这次尝试在文档上触发另一个事件,称为“tabsLoaded”并等待该响应,它可以工作,但它开始有点令人困惑。

我想知道是否有人有更好的解决方案吗?选项卡和滑块也可以作为独立工作,也可以只使用没有滑块关联的选项卡。

非常感谢 !

这是我的标签插件:

(function($) {
  let pluginName = 'Tabs';

  function Tabs(element, options) {
    let settings = {};

    this.element = element;
    this.$element = $(this.element);
    this.settings = $.extend({}, settings, options);

    this.children = null;
    this.activeTabIndex = 0;
    this.nbTabs = 0;

    this.init();
  }

  $.extend(Tabs.prototype, {

    init: function() {
      this.children = this.$element.children();
      this.nbTabs = this.children.length;

      // Listeners
      this.children.on('click', {
        tabs: this
      }, this.onTabChange); // Click on a tab
      $(this).on('tabChange', this.setActive);

      // On Init, active the first tab
      if (this.children && this.nbTabs > 0) {
        $(this).trigger({
          type: 'tabChange',
          tab: this.children.first().index(),
        });
      }

      $(document).trigger({
        type: 'tabLoaded',
        tabs: this,
      });
    },
    setActive: function(event) {
      this.activeTabIndex = event.tab;
      this.children.eq(this.activeTabIndex).addClass('is-active');
    },
    onTabChange: function(event) {
      event.preventDefault();
      const tabs = event.data.tabs;
      // Reset active classes
      tabs.children.removeClass('is-active');
      // Launch changeTab
      $(tabs).trigger({
        type: 'tabChange',
        tab: tabs.children.index(event.currentTarget),
      });
    }
  });

  $.fn[pluginName] = function(options) {
    return this.each(function() {
      if (!$.data(this, pluginName)) {
        $.data(this, pluginName, new Tabs(this, options));
      }
    });
  };
})(jQuery);

jQuery(document).ready(function($) {
  $('.js-tabs').Tabs();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

这是我的滑块插件监听标签:

(function($) {
  let pluginName = 'Slider';

  function Slider(element, options) {
    let settings = {};

    this.element = element;
    this.$element = $(this.element);
    this.settings = $.extend({}, settings, options);

    this.id = null;
    this.tabs = null;
    this.children = null;
    this.activeSlideIndex = 0;
    this.nbSlides = 0;

    this.init();
  }

  $.extend(Slider.prototype, {

    init: function() {
      this.id = this.$element.attr('id');
      this.children = this.$element.children();
      this.nbSlides = this.children.length;
      // Listeners
      // Click on slide
      this.children.on('click', {
        slider: this
      }, this.onSlideChange);
      // On slide change
      $(this).on('slideChange', {
        slider: this
      }, this.onSlideChange);
      $(this).on('change', this.update);

      // On Init, active the first tab
      if (this.children && this.nbSlides > 0) {
        $(this).trigger({
          type: 'slideChange',
          slide: this.children.first().index(),
        });
      }
      $(document).trigger({
        type: 'sliderLoaded',
        slider: this,
      });
    },
    update: function() {
      // if Slider has an associated Tabs
      if (this.tabs) {
        $(this.tabs).on('tabChange', {
          slider: this
        }, this.onTabChange);
      }
    },
    onSlideChange: function(event) {
      event.preventDefault();
      const slider = event.data.slider;
      const slide = event.slide;
      // Reset active classes
      slider.children.removeClass('is-active');
      slider.activeSlideIndex = slide ? slide : event.currentTarget;
      console.log(slider.activeSlideIndex);
      slider.children.eq(slider.activeSlideIndex).addClass('is-active');
    },
    // TABS
    onTabChange: function(event) {
      const slider = event.data.slider;
      const tabIndex = event.tab;
      if ($(slider.children).eq(tabIndex).length >= 0) {
        $(slider).trigger({
          type: 'slideChange',
          slide: tabIndex,
        });
      }
    }
  });

  $.fn[pluginName] = function(options) {
    return this.each(function() {
      if (!$.data(this, pluginName)) {
        $.data(this, pluginName, new Slider(this, options));
      }
    });
  };
})(jQuery);

jQuery(document).ready(function($) {
  $('.js-slider').Slider();
});

// On Tabs loaded, insert it into slider
jQuery(document).on('tabLoaded', function(event) {
  const tabs = event.tabs;
  const sliderId = jQuery(tabs.element).data('slider-id');
  if (jQuery('#' + sliderId).first().data('Slider')) {
    const slider = jQuery('#' + sliderId).first().data('Slider');
    slider.tabs = tabs;
    slider.update();
  }
});
答案

我跟着@Anton的建议,我拆分了我的标签和滑块,它工作得很好:)

  • 首先,我从插件的文件中删除了插件的插件。
  • 然后我把每个inits放到我称为“app.js”的另一个文件中

我的App.js看起来像这样:

jQuery(document).ready(function ($) {
    let $sliders = $('.js-slider').Slider();
    let $tabs = $('.js-tabs').Tabs();

    $sliders.on('slideChanged', function (event) {
        const sliderId = $(this).attr('id');
        const slide = event.slide;
        $tabs.filter('[data-slider-id=' + sliderId + ']').data('Tabs').select(slide);
    });

    $tabs.on('tabChanged', function (event) {
        const sliderId = $(this).data('slider-id');
        const tab = event.tab;
        $sliders.filter('#' + sliderId).data('Slider').select(tab);
    });
});

以上是关于创建2个可以相互通信的jquery插件的主要内容,如果未能解决你的问题,请参考以下文章

几个可以直接拿来用的jQuery代码片段

几个非常实用的JQuery代码片段

几个实用的 jQuery 插件

web前端开发JQuery常用实例代码片段(50个)

可以直接拿来用的15个jQuery代码片段

与另一个片段通信的片段接口