2012-04-12 73 views
46

我正在使用knockout.js來構建動態列表,並且試圖弄清楚如何獲取與可觀察數組中的對象關聯的DOM對象。具體而言,我想獲得一行jQuery。Knockout.js獲取與數據相關聯的dom對象

例子:

<ul data-bind="foreach: Item"> 
    <li data-bind="events: {click: getDomObject}, text: 'text: ' + text"> 
    </li> 
</ul> 
getDomObject功能

,我希望能夠得到具體<li></li> DOM對象,以便我可以做一些jQuery的操縱它。

我想過在項目ViewModel中添加一個id成員,然後添加該id作爲該項目的html id,然後選擇基於該項目,但我覺得應該有一個更簡單的方法。

引用knockout.js生成的動態HTML的正確方法是什麼?

回答

64

像點擊這樣的事件處理程序傳遞了兩個參數。那是a)這個事件所屬的項目 - 就像你用foreach綁定(你的案例中的「Item」)呈現的可觀察數組的條目。和b)一個事件對象,爲您提供有關實際事件的更多信息。這個對象包含得到點擊(重點「目標」)的DOM元素:

getDomObject = function(item, event) { 
    var $this = $(event.target); 
    // ... 
} 

只是注意:不要混合淘汰賽和本地jQuery的DOM操作 - 如果你能達到與巧妙的淘汰賽綁定相同的結果,我會建議去那個。

這裏是一個簡單的演示:http://jsfiddle.net/KLK9Z/213/

+0

非常感謝!這很好用!感謝有關jQuery操作的負責人。我在特定的行上使用了自動完成功能,所以我認爲我不能通過ko來完成。偉大的解決方案 – 2012-04-12 16:31:11

+0

使用自動完成padawan的自定義綁定。 :P在與ko開發3個月後學到了一件事:使用jquery/jquery ui東西的自定義綁定。 – 2013-02-19 02:02:41

+0

我曾與淘汰賽的年齡,並沒有意識到事件參數 - 輝煌!謝謝 – 2013-08-08 04:05:41

20

$(event.target)的解決方案是好的,如果是涉及到一個已經發生的事件進行該產品的DOM元素爲目標。但有時你沒有目標項目,因爲沒有事件(例如 - 你想滾動列表到用戶未指示的項目)。

在這種情況下,您可以給項目的DOM元素的id屬性,它包含項目ID的唯一值:

<li data-bind="attr: {id: 'item_' + id}"> 

,然後getDomObject()看起來像:

getDomObject = function(item) { return $("#item_" + item.id); } 
+0

恕我直言,這個答案是完全正確的原因yuvalr80陳述。 – 2012-09-17 19:08:55

+0

這個答案是我所需要的,但接受的答案對原始問題更好。感謝您張貼這個答案,但是,正是我所需要的。對於跨越MVVM的界限並不着迷,但我只是需要一種有效的方式來滾動項目以查看,並且不希望爲列表中的每個對象添加額外的可觀察項。 – eselk 2013-02-18 03:14:12

+1

它的工作原理是傳遞ID,然後通過該ID獲取DOM。它打破了一些規則。任何非ID解決方案將不勝感激。 – 2013-06-11 13:08:52

7

又添加第三種選擇,也適用於沒有事件處理的情況(如果您有事件,則接受的答案是最佳/最佳的)。

創建自定義的結合,例如:

ko.bindingHandlers.scrollTo = { 
    update: function(element, valueAccessor) { 
     var value = ko.utils.unwrapObservable(valueAccessor()); 
     if (value) { 
      var scrollParent = $(element).closest("div"); 
      var newTop = $(element).position().top + scrollParent.scrollTop(); 
      scrollParent.scrollTop(newTop); 
     } 
    } 
}; 

用法如下:

<li data-bind="scrollTo: $parent.scrollTo() && $parent.scrollTo().id == id"> 

在上述情況下,$父是我的視圖模型。我有一個可觀察的對象,其中包含一個唯一的ID。每次我設置scrollTo()對象時,列表都會滾動到該項目。

請注意,我的代碼假設LI的父DIV有滾動條(溢出:自動/滾動)。您可以根據自己的需要進行調整,可以在父級上使用一個類並將其用於jQuery選擇器,或者可以非常靈活地通過數據綁定選項傳遞給選擇器...對我來說,這足夠了,因爲我總是使用div作爲我的可滾動部分。

+0

我做了類似的事情,效果非常好!感謝這篇文章 – 2013-02-18 21:10:58

1

我有類似的問題。我想出了一個類似於Backbone.js使用el和$ el引用的解決方案。

在您的視圖模型

var myViewModel = function(){ 
    var self = this; 

    //html element 
    self.el = ko.observable(); 

    //jquery wrapped version 
    self.$el = ko.observable(); 
} 

在HTML(例如列表元素):

<!-- left side is the name of the handler, right side is name of the observable --> 
<li class="myclass" data-bind="el: el, $el: $el"></li> 

在bindingHandlers(顯示所有可能的參數初始化):

ko.bindingHandlers.el = { 
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) { 
    var value = valueAccessor(); 
    //assign value to observable (we specified in html) 
    value(element); 
    } 
}; 

ko.bindingHandlers.$el = { 
    init: function(element, valueAccessor, allBindings, viewModel, bindingContext) { 
    var value = valueAccessor(); 
    //here we first create a jQuery object by using $(myelem) 
    //before updating observable value 
    value($(element).first()); 
    } 
}; 

例如,那麼你可以使用$ el如:

var myViewModel = function(){ 
    var self = this; 

    //plain DOM element reference 
    self.el = ko.observable(); 

    //jquery object reference 
    self.$el = ko.observable(); 

    self.myFunction = function() { 
    console.log(self.$el().html()); 
    self.$el().addClass("myCssClass"); 
    } 
} 

希望這有助於!

1

我的解決方案(適用於 「價值」 的結合)

ko.bindingHandlers.value.preprocess = function(val, name, cb) { 
    /* every time I set a data-bind="value: xxxx" with an 
    * observable xxxx add also a data-bind="domElement: xxxx" */ 
    cb('domElement', val); 
    return val; 
} 

ko.bindingHandlers.domElement = { 
    /* For each data-bind="domElement: xxxx" add an extension "element" */ 
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) { 
     valueAccessor().extend({element: element }); 
    } 
    }; 

ko.extenders.element = function (target, element) { 
    /* element extension add el and $el to observable xxxx */ 
    target.el = element; 
    target.$el = $(element); 
} 

現在你有yourobservable。$ E1和yourobservable.el結合到jQuery和DOM元素。