Knockout.js获取与数据关联的dom对象

我正在与knockout.jsbuild立dynamic列表,我想弄清楚如何可以得到DOM对象与我的可观察数组中的对象相关联。 具体而言,我想获得一行jQuery。

例:

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

getDomObject函数中,我希望能够获得特定的<li></li> DOM对象,以便我可以对它进行一些jQuery操作。

我想添加一个id成员到项目ViewModel,然后添加id作为行项目的html id,然后select基于此,但我觉得应该有一个更简单的方法。

引用knockout.js生成的dynamicHTML的正确方法是什么?

像click这样的事件处理程序传递了两个参数。 那是a)这个事件所属的项目 – 就像你用foreach绑定(你的案例中的“Item”)呈现的一个可观察数组的条目。 和b)一个事件对象,为您提供有关实际事件的更多信息。 该对象包含被点击的DOM元素(键“target”):

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

请注意:不要将knockout和原生jQuery DOM操作混合在一起 – 如果您可以使用巧妙的挖空绑定来实现相同的结果,那么我会推荐使用它。

这里是一个简单的演示: http : //jsfiddle.net/KLK9Z/213/

$(event.target)解决scheme如果与已经发生的项目的DOM元素位于目标的事件相关,那么它是很好的解决scheme。 但有时你没有目标项目,因为没有事件(例如 – 你想滚动一个列表到一个没有用户手势的项目)。

在这种情况下,您可以为项目的DOM元素ID属性指定一个包含项目ID的唯一值:

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

然后getDomObject()看起来像:

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

要添加第三个选项,对于没有事件处理的情况(如果有事件,则接受的答案是最佳的/优化的)。

创build一个自定义绑定,如:

 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"> 

在上面的例子中,$ parent是我的View Model。 我有一个可观察的对象,其中包含一个唯一的ID。 任何时候我设置scrollTo()对象,列表滚动到该项目。

请注意,我的代码假设LI的父DIV有滚动条(溢出:自动/滚动)。 您可以根据自己的需要进行调整,可以在父级上使用一个类,并将其用于jQueryselect器,或者使其非常灵活,您可以通过数据绑定选项传递select器…对于我来说,这已经足够了我总是用我的可滚动部分的div。

我有一个类似的问题。 我想出了一个类似Backbone.js的el和$ el引用的解决scheme。

在你的ViewModel中:

 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(显示init的所有可能的参数):

 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"); } } 

希望这可以帮助!

我的解决scheme(有效的“价值”绑定)

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

现在你已经有了可以pipe理的$ el和yourobservable.el,它们绑定了jquery和DOM元素。