2

ハイパーリンクをクリックしたときに直接アクセスしたいjQueryオブジェクトがある単純なクライアント側インターフェースに取り組んでいます。簡略化されたコード:

<div class="controls">
    <div class="score">
        <a class="button" href="/add">Add points!</a>
    </div>
</div>


$(".controls").myControls();

$.fn.myControls = function() {
    return $.extend(this, $.myControls).initialize();
}

$.myControls = {
    initialize: function() {
        this.scoreElement = $("div.score", this);
        this.linkElement  = $("a", this.scoreElement);

        this.scoreElement.score = 0;

        var _this = this;
        this.linkElement.click(function() {
            _this.clickHandler(this);
        });
    },
    clickHandler: function(element) {
        var scoreElement = $(element).parent();
        scoreElement.score = 1;
    }
}

説明:.controls要素には.score、スコア情報 ( ) のコンテナーを兼ねる要素がありthis.scoreElement.scoreます。要素内のリンクをクリックすると.score、DOM と同じ要素である親要素が見つかり、そのプロパティを 1 にthis.scoreElement設定しようとします。メソッドのローカルプロパティが"未定義"。scorescoreElement.scoreclickHandler

ここに私の質問this.scoreElementがあります。jQuery を使用して DOM をトラバースして、オブジェクトに直接アクセスする簡単な方法はありますか?

確かにthis.scoreElement == $(element).parent()、何らかの方法でオブジェクトの正しいプロパティにアクセスできるかどうかを確認できthis.scoreElementますが、直接アクセスする方がエレガントで堅牢です。これは可能ですか?私は間違った方法で進んでいますか?ありがとう!

parent()PS:を見つけるために使用するという事実は無視してscoreElementください。問題を説明するためにのみ使用します。それが問題の一部でない限り、その場合は無視しないでください:)

4

3 に答える 3

3

独自の「コントロール オブジェクト」を使用して関連データを格納することは確かに可能ですが、私は通常、次のように.data()メソッドを使用して jQuery に依存することを好みます。

$(this.scoreElement).data('score', 0); // in initialize()
$(this).parent().data('score', 1); // in clickHandler()

このアプローチにより、要素のオブジェクトではなく単一の「コントロール」オブジェクトを使用して、「重複」の問題を心配する必要がないため、より簡単にスケーリングできます。

于 2012-06-23T17:42:13.613 に答える
1

クリック ハンドラーに jQuery のプロキシ関数を使用した場合、this.scoreElement を clickHandler 内に移動するだけで、DOM をトラバースする必要さえないと思います。このような:

$.myControls = {
    initialize: function() {
        this.scoreElement = $("div.score", this);
        this.linkElement  = $("a", this.scoreElement);

        this.scoreElement.score = 0;

        this.linkElement.click($.proxy(this.clickHandler, this));
    },
    clickHandler: function(event) {
        var element = event.target;
        this.scoreElement.score = 1;
    }
}
于 2012-06-23T17:19:19.257 に答える
1

漸進的な単純化 (およびスコアの保存方法が少し異なる) の後、以下のコードを取得します。このコードscoreElementは div ごとに 1 回検出さ.controlsれ、対応するクリック ハンドラーで使用できるようにクロージャーに保持されます。代わりに使用することもできます.closest()-コメントアウトされた行を参照してください。

$.fn.myControls = function() {
    return this.each(function() {
        var scoreElement = $("div.score", $(this));
        scoreElement.data('score', 0);
        $("a", scoreElement).on('click', function() {
            scoreElement.data('score', 1);//get scoreElement from closure formed by the outer "each" function.
            //$(this).closest(".score").data('score', 1);//alternative to the line above, not requiring closure.
        });
    });
};

質問のように次のように呼び出します。

$(".controls").myControls();    

これは非常に些細で一次元的なものであるため、それ自体で jQuery プラグインを使用する必要はありません。プラグインにやむを得ない理由 (再利用や密接に関連するメソッドの必要性など) がない限り、次のように表現します。

$(".controls").each(function() {
    var scoreElement = $("div.score", $(this));
    scoreElement.data('score', 0);
    $("a", scoreElement).on('click', function() {
        scoreElement.data('score', 1);//get scoreElement from closure formed by the outer "each" function.
        //$(this).closest(".score").data('score', 1);//alternative to line above, not requiring closure.
    });
}); 

これは、プラグイン ラッパーが削除され、同じベース jQuery オブジェクトに直接アタッチされた同じコードです。

どうしてもやりたい場合は、次のように 3 行ですべてを記述できます。

$(".controls").find("div.score").data('score', 0).find("a.button").on('click', function() {
    $(this).closest(".score").data('score', 1);
});
于 2012-06-25T00:39:30.143 に答える