1

特定のアクションの各ハンドラーがターゲット要素に直接アタッチされていた古いイベント管理は、パフォーマンスとメモリ節約に関する考慮事項が開発者コミュニティに広まり始めたため、時代遅れになりつつあります。

jQuery が旧式のメソッド.bind().live()メソッドを新しい.on()メソッドで更新して委任を可能にしてから、イベント委任の実装が加速しました。

これにより、一部の経験豊富なアプローチの変更が決定され、イベント委任を使用する場所で手直しが必要になります。ライブラリのコーディング スタイルを維持しながら、いくつかのベスト プラクティスを考え出そうとしています。答えを見つけるために、他の開発者が直面している同様の状況を探しました。

関数をコンストラクターとして OOP を使用すると、通常、次のようなオブジェクト作成用のインターフェイスがあります。

var widget = new Widget({
    timeout: 800,
    expander: '.expanders'
});

オブジェクトリテラルを引数として指定し、渡された入力の名前と値のクリーンなマップを提供します。このコードの基礎となるクラスは、次のようになります。

var Widget = function(options) {
    // some private members
    var _timeout;
    var _$widget;
    var _$expander;

    // methods
    this.init = function() {
        _timeout = options.timeout || 500;
        _$expander = $(options.expander);
        _$widget = _$expander.next();
        _$expander.on('click', _toggle);
    };
    var _toggle = function(e) {
        if (_$widget.is(':visible')) {
            _$widget.hide(_timeout);
        } else {
            _$widget.show(_timeout);
        }
    };
    this.init();
};

「プライベート」メソッドを使用すると、コードの読みやすさとクリーンさの点でいくつかの利点が得られました (有用なメソッドのみがユーザーに公開されます)。パフォーマンスのわずかな向上 (各スコープ解決はローカル変数よりも時間がかかります) を超えています。しかし、イベント ハンドラーについて話すと、イベント委任パラダイムと衝突します。

クラスのリスナーに内部的に関連付けるために使用したメソッドを公開することを考えました。

    this.toggle = function(e) {
        if (_$widget.is(':visible')) {
            _$widget.hide(_timeout);
        } else {
            _$widget.show(_timeout);
        }
    };

次に、外部または別のプロキシ クラスで、次のような適切な委譲を実行します。

var widget = new Widget({
    expander: '.expanders'
});

$(delegationContext).on('click', '.expanders', widget.toggle);

しかし、それは私には最善のアプローチではないように思えました。インターフェイスで役に立たないメソッドの公開に失敗したため、メインクラスにすべての情報を直接知らせて、イベントを自律的に委譲する方法をインターフェイスを介して試みました。

var widget = new Widget({
    timeout: 800,
    expander: {
        delegationContext: '.widgetContainer',
        selector: '.expanders'
    }
});

これにより、クラス内で内部的にプライベート メソッドを使用し続けることができます。

var $context = $(options.expander.delegationContext);
$context.on('click', options.expander.selector, _toggle);

それについてのあなたの実践と提案は何ですか?
また、今日までに聞いた他の開発者の主な傾向は何ですか?

4

1 に答える 1

0

それはイベント委任パラダイムと衝突します。

そのパラダイムを忘れてください!「かっこいい」「イベントを直接付けるのは時代遅れになっている」という理由で選択しないでください。必要な場合にのみ選択してください。イベント委譲は必要ありませんし、速度も向上しませんこれは適用できるソリューションではありません。問題ありません。

1 つの要素と、1 つの要素固有のイベント ハンドラー関数があります (すべてのウィジェット エキスパンダーには独自の関数があります)。イベント委任を適用する際の問題から、ここでは使用できない、また使用すべきではないことを既に推測できます。ハンドラーを直接アタッチします。

イベントの委譲は、大量の同様の要素が DOM 内に一貫して配置され、共通の祖先が 1 つあり、それらすべてが同じイベント ハンドラー関数に関連付けられる場合にのみ役立ちます。これは、セレクターWidgetなどのインスタンス固有のオプションを取るコンストラクターには当てはまりません。expander

現在のクラスでは、イベント委任を使用すると、単一責任の原則Widgetと衝突します。イベント委譲パラダイムでは、委譲コンテキスト内の要素を全体として見て、可能な限り均一にする必要があります。要素固有のデータと状態を追加すればするほど、委譲の利点が失われます。

ここで本当にイベント委任を使用したい場合は、次のようなものをお勧めします

var Widgets = {
    init: function(delegationContext) {
        $(delegationContext).on("click", ".widget-expander", function(e) {
             $this = $(this);
             $this.next().toggle($this.data("widget-expander-timeout") || 500);
        });
    },
    activate: function(options) {
        $(options.expander)
         .addClass("widget-expander")
         .data("widget-expander-timeout", options.timeout);
    }
};

ここでは、コンストラクターは使用されません。イベント委任コンテキストを初期化するだけで、委任メカニズムによってキャプチャされる単一の要素を追加できます。すべてのデータは要素に格納され、イベント ハンドラーからアクセスできます。例:

Widgets.init('.widgetContainer');
Widgets.activate({expander: '.expanders', timeout: 800});

また、今日までに聞いた他の開発者の主な傾向は何ですか?

その質問が StackOverflow の話題から外れていることを除けば、誰かが聞いたすべての傾向に従わないようにアドバイスすることしかできません。はい、新しい(または宣伝されている、または派手な)テクノロジーについて学びますが、それらをいつ使用するかについて学ぶことを忘れないでください.

于 2013-09-15T23:47:31.647 に答える