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

时间:2018-03-02 11:17:02

标签: javascript jquery plugins javascript-events extends

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

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

    我开始创建事件监听器和触发器,当点击我的标签时,一个事件' 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>
    &#13;
    &#13;
    &#13;

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

    &#13;
    &#13;
    (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();
      }
    });
    &#13;
    &#13;
    &#13;

1 个答案:

答案 0 :(得分:0)

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

  • 首先,我删除了我的插件&#39;来自插件&#39;文件。
  • 然后我将每个inits放入另一个我称之为#34; app.js&#34;
  • 的文件中

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

&#13;
&#13;
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);
    });
});
&#13;
&#13;
&#13;

我正在倾听每一个发送过的事件,例如“幻灯片改变”,或者“改变”&#39; tabChanged&#39;然后我通过匹配的ID获得正确的标签或滑块实例。

这是我的标签代码:

&#13;
&#13;
(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.onTabClick); // Click on a tab
      $(this).on('tabChanged', this.onTabClick);

      // On Init, active the first tab
      if (this.children && this.nbTabs > 0) {
        this.children.first().click();
      }
    },
    select: function(tab) {
      // Reset active classes
      this.children.removeClass('is-active');
      this.activeTabIndex = tab;
      this.children.eq(tab).addClass('is-active');
    },
    onTabClick: function(event) {
      event.preventDefault();
      const tabs = event.data.tabs;
      const tab = tabs.children.index(event.currentTarget);
      tabs.select(tab);
      // Launch changeTab
      $(tabs.element).trigger({
        type: 'tabChanged',
        tab: tab,
      });
    }
  });

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

和滑块:

&#13;
&#13;
(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.onSlideClick);
      // On slide change
      $(this).on('slideChanged', this.onSlideClick);

      // On Init, active the first tab
      if (this.children && this.nbSlides > 0) {
        this.children.first().click();
      }
    },
    select: function(slide) {
      // Reset active classes
      this.children.removeClass('is-active');
      this.activeSlideIndex = slide;
      this.children.eq(this.activeSlideIndex).addClass('is-active');
    },
    onSlideClick: function(event) {
      event.preventDefault();
      const slider = event.data.slider;
      const slide = slider.children.index(event.currentTarget);
      slider.select(slide);
      // Launch changeTab
      $(slider.element).trigger({
        type: 'slideChanged',
        slide: slide,
      });
    },
  });

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