直接通过DOM遍历jQuery访问javascript对象

时间:2012-06-23 16:33:17

标签: javascript jquery dom traversal

我正在开发一个简单的客户端界面,我有一个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属性是“未定义的”。

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

当然,我可以通过某种方式检查是否this.scoreElement == $(element).parent(),然后访问我的this.scoreElement对象中的正确属性,但直接访问会更优雅,更健壮。这可能吗?我是以错误的方式去做的吗?谢谢!

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

3 个答案:

答案 0 :(得分:3)

虽然使用你自己的'control-object'来存储相关数据当然是可能的,但我通常更喜欢依赖jQuery来做 - 使用.data()方法,如下所示:

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

这种方法允许我更容易扩展,因为我从不必担心“重叠”问题,使用单个“控制”对象而不是对象元素。

答案 1 :(得分:1)

我认为如果你为你的点击处理程序使用了jQuery的代理函数,那么你就可以在clickHandler中使用this.scoreElement,你甚至不需要遍历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;
    }
}

答案 2 :(得分:1)

逐渐简化(并且将得分略有不同)我得到下面的代码,其中scoreElement.controls个div发现一次,然后保存在一个闭包中以使其可用于相应的点击处理程序您也可以使用.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);
});