我正在使用knockout.js来构建动态列表,我正在试图找出如何在可观察数组中获取与对象关联的DOM对象。具体来说,我想连续获取jQuery。
示例:
<ul data-bind="foreach: Item">
<li data-bind="events: {click: getDomObject}, text: 'text: ' + text">
</li>
</ul>
在getDomObject
函数中,我希望能够获取特定的<li></li>
DOM对象,以便我可以使用它进行一些jQuery操作。
我已经考虑过将id
成员添加到Item ViewModel中,然后将id添加为行项目的html id,然后根据它进行选择,但我觉得应该有一个更简单的方法。
引用knockout.js生成的动态HTML的正确方法是什么?
答案 0 :(得分:66)
像click这样的事件处理程序传递了两个参数。那是
此事件所属的项目 - 就像您使用foreach绑定呈现的可观察数组的条目(在您的情况下为“Item”)。
并且是一个事件对象,它为您提供有关实际事件的更多信息。此对象包含单击的DOM元素(键“target”):
getDomObject = function(item, event) {
var $this = $(event.target);
// ...
}
请注意:不要混用淘汰赛和原生jQuery DOM操作 - 如果你能通过巧妙的淘汰赛绑定获得相同的结果,我建议你去做。
这是一个简单的演示:http://jsfiddle.net/KLK9Z/213/
var Item = function(color) {
this.color = String(color);
this.setTextColor = function(item, event) {
$(event.target).css('background', color);
};
};
ko.applyBindings(new function() {
this.Items = ko.observableArray([
new Item('red'),
new Item('blue'),
new Item('green')
]);
}());
li {
padding: 2px 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/2.0.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<ul data-bind="foreach: Items">
<li>
<button data-bind="click: setTextColor, text: 'Color: ' + color"></button>
</li>
</ul>
答案 1 :(得分:20)
如果 $(event.target)解决方案与项目的DOM元素所在的已发生事件相关,则该解决方案很好。但有时你没有目标项目,因为没有事件(例如 - 你想将列表滚动到一个没有被用户手势的项目。)
在这种情况下,您可以为项目的DOM元素id属性提供包含项目ID的唯一值:
<li data-bind="attr: {id: 'item_' + id}">
然后getDomObject()看起来像:
getDomObject = function(item) { return $("#item_" + item.id); }
答案 2 :(得分:7)
要添加第3个选项,也适用于没有要使用事件的情况(如果您有事件,则接受的答案最佳/优化)。
创建自定义绑定,例如:
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具有滚动条(overflow:auto / scroll)。您可以根据自己的需要进行调整,可能在父级上使用一个类并将其用于jQuery选择器,或者使您可以通过数据绑定选项传递选择器非常灵活...对我来说,这就足够了,因为我总是将div用于我的可滚动部分。
答案 3 :(得分:5)
我有类似的问题。我提出了类似Backbone.js使用el和$ el引用的解决方案。
在您的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");
}
}
希望这有帮助!
答案 4 :(得分:4)
我的解决方案(适用于&#34;值&#34;绑定)
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。$ el和yourobservable.el绑定到jquery和DOM元素。