模块化/客观化JQuery

时间:2014-05-23 16:16:58

标签: javascript jquery oop modular-design

我有许多不同的控制元素"在我的应用程序:下拉菜单,选项卡,菜单等。在相同的页面上,有许多相同的控件。在编写JavaScript来处理与每个控件相关的不同事件时,我试图尽可能地将我的代码设置为DRY。其中一个挑战是模块化我的JQuery代码,以便在特定控件中发生的事件仅影响该控件。

以这个初始代码为例,它所做的就是点击它时打开一个下拉菜单。我过去常常只编写由不同事件触发的大量不同的匿名函数,所以这种类型的JQuery对我来说真的很新。

var dropdown = {
  init: function() {
    $(".dropdown").click(".dropdown", dropdown.openDropdown);
  },  
  openDropdown: function() {
    $(this).children(".dropdown-menu").show();
    $(this).addClass("open");
  }
}

$(document).ready(dropdown.init);

我的问题是,在这个dropdown变量中,我希望能够保存/跟踪当前正在执行的dropdown控件的不同部分。例如,我可能想写:

var menu = $(this).children(".dropdown-menu");

在这个块中的某个地方,这样我可以在调用不同的函数时返回这个菜单。我只是无法弄清楚如何做到这一点。欢迎任何帮助/指导!感谢。

3 个答案:

答案 0 :(得分:3)

我喜欢coffeescript的内容是如何让您轻松创建 classes 。咖啡中的类只是生成"模块的简单方法。使用javascript的原型继承。更多相关内容:http://coffeescript.org/#classes

但是你如何实现更多的模块化jQuery代码就是做这样的事情:

http://jsfiddle.net/x858q/2/

var DropDown = (function(){
    // constructor
    function DropDown(el){
        this.el = $(el);
        this.link = this.el.find("a");
        this.menu = this.el.find(".dropdown-menu");
        this.bindClick();
    }

    // method binding click event listener
    DropDown.prototype.bindClick = function(){
        var _this = this;
        this.link.click(function(e){
            _this.openDropDown();
            e.preventDefault();
        });
    };

    // click event handler
    DropDown.prototype.openDropDown = function(){
        this.menu.show();
        this.link.addClass("open");
    };

    return DropDown;
})();

$(function(){
    // init each .dropdown element as a new DropDown
    $(".dropdown").each(function(){
       new DropDown(this); 
    });
});

答案 1 :(得分:1)

你已经触及了我越来越倾向于的模式。基本上,创建一个JavaScript对象,在页面上给定根元素的情况下充当控制器。由于这个“下拉列表”非常通用,它可能可以访问整个页面并且非常高兴。我还建议制作这些“模块”可实例化的对象,因为这样可以更容易地编写单元测试:

function DropdownModule() {
    this.handleClick = this.handleClick.bind(this);
}

DropdownModule.prototype = {

    element: null,

    $element: null

    constructor: DropdownModule,

    init: function(element) {
        this.setElement(element);
        this.$element.on("click", ".dropdown", this.handleClick);
    },

    handleClick: function(event) {
        var $dropdown = $(event.currentTarget);
        $dropdown.children(".dropdown-menu").show();
        $dropdown.addClass("open");

        this.someOtherFunction($dropdown);
    },

    someOtherFunction($dropdown) {
        // do something with $dropdown
    },

    setElement: function(element) {
        this.element = element;
        this.$element = $(element);
    }

}

然后使用它,只需在Dropdown

的定义之后将其抛出
var dropdown = new Dropdown()
    .init(document.documentElement);

document.documentElement属性引用<html>标记,并在JavaScript开始执行时可用。

作为旁注,我围绕这种方法构建了一个完整的框架:Foundry。其他框架,如Angular,也采用了类似的方法。

答案 2 :(得分:1)

您想要的听起来就像jQuery UI已经在Widget Factory中实现的那样。

我强烈建议你查看它,因为你最终会得到它像

$.widget( 'dropdown', {
  _create: function() {
    this.element.addClass( 'dropdown' );

    this._on({
      'click': '_clicked'
    });
  },

  _clicked: function( event ) {
    // `this` is an instance of dropdown here, not the element
    this.clicked = !this.clicked;

    this.element.toggleClass( 'clicked', this.clicked );  
  },

  _destroy: function() {
    this.element.removeClass( 'dropdown' );
  }
});

然后你会像任何其他jQuery UI Widget一样使用它

$( '#some-element' ).dropdown();