2012-06-23 71 views
2

我正在研究一個簡單的客戶端接口,其中我有一個jQuery對象,當我單擊一個超鏈接時,我想直接訪問它。簡化的代碼:通過DOM遍歷jQuery直接訪問javascript對象

<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的事實,我只用它來說明我的問題。除非它是問題的一部分,在這種情況下,不要忽略:)

+0

這一切都非常令人費解。你究竟在努力實現什麼? –

+0

我實際上構建的是一個簡單的骰子游戲,通過點擊與骰子相關的鏈接可以「保留」任何骰子;這個鏈接是構成死亡的DOM元素的一個子元素。我認爲我最好爲每個死亡構建一個單獨的對象,這會讓我的問題消失,但我仍然想通過獲得一個很好的解決方案/回答我的問題來學習一點。 – Phortuin

回答

3

雖然的確可以使用自己的「控制目標」來存儲相關數據,我通常喜歡依賴jQuery的做這件事 - 與.data()方法,像這樣:

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

這種方法使我可以更容易地擴展,因爲我從來不用擔心'重疊'問題,只需使用一個'control'對象而不是object-for-element。

+0

好的,這將工作,聽起來像一個堅實的解決方案,但可悲的是不太可讀。你能否爲你的「縮放」論點做個案,也許是一個簡單的例子?謝謝! – Phortuin

1

我會認爲,如果您使用jQuery的代理函數爲您的點擊處理程序,然後你可以只是在clickHandler裏面this.scoreElement,你wouldn甚至不需要遍歷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; 
    } 
} 
+0

這將是一個很好的答案,但(可能我並沒有完全清楚我的問題)'this.scoreElement'不只是一個單一的元素,但它涉及到被點擊的鏈接。所以,'event.target'(鏈接元素)應該指向它的'scoreElement',這是我的問題:這個'scoreElement'在哪裏直播,我如何直接訪問它?如果'this.scoreElement'是'$ .myControls'中存在的單個對象,你的回答只能解決我的問題。但是,無論如何感謝:) – Phortuin

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); 
}); 
+0

謝謝!我同意你說的一切,這裏解決方案的核心是jQuery的'.data()'方法,raina77ow也說過。如果你不介意的話,我會回答他的答案。當然,我的實際代碼比我在這裏作爲一個例子寫的要複雜一些,但是你明確指出這個特殊的位不能保證插件。但是再一次,它確實使代碼更具可讀性和可擴展性。 – Phortuin