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 中的元素相同,this.scoreElement并尝试将其score属性设置为 1。显然,这不起作用,因为方法中的本地scoreElement.score属性clickHandler是“不明确的”。

所以这是我的问题:this.scoreElement有没有一种简单的方法可以通过使用 jQuery 遍历 DOM 来直接访问我的对象?

当然,我可以检查是否this.scoreElement == $(element).parent()以某种方式访问this.scoreElement​​对象中的正确属性,但直接访问会更加优雅和健壮。这可能吗?我是不是走错路了?谢谢!

PS:忽略我parent()用来查找的事实scoreElement,我只是用它来说明我的问题。除非它是问题的一部分,否则在这种情况下不要忽略:)

4

3 回答 3

3

虽然当然可以使用您自己的“控制对象”来存储相关数据,但我通常更喜欢依靠 jQuery 来做这件事——使用.data()方法,如下所示:

$(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 发现一次.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 对象的代码相同。

如果你真的想要,你可以把整个事情写成三行,如下所示:

$(".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 回答