0

アプリケーションには、ドロップダウン、タブ、メニューなど、さまざまな「コントロール要素」があります。同じページに、同じコントロールが多数あります。これらの各コントロールに関連付けられたさまざまなイベントを処理する JavaScript を作成するとき、コードをできるだけ DRY にしようとしています。課題の 1 つは、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");

このチャンクのどこかにあるので、さまざまな関数を呼び出すときにこのメニューを参照できます。これを行う方法を構文的に理解することはできません。ヘルプ/ガイダンスは大歓迎です! ありがとう。

4

3 に答える 3

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); 
    });
});
于 2014-05-23T20:09:24.790 に答える
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 などの他のフレームワークも同様のアプローチをとっています。

于 2014-05-23T20:04:39.067 に答える
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 ウィジェットと同じように使用します。

$( '#some-element' ).dropdown();
于 2014-05-23T21:45:26.253 に答える