假设你从一个通过jquery完成UI影响的网站开始。例如,菜单。 单击定位点将对此应用一个类,以显示定位点是活动定位点。 这是在 dom ready 上的 jquery 中完成的 -
$(function() {
$("#menu a").click(function(){
$("#menu a").removeClass('active');
$(this).addClass('active');
});
});
现在,假设此菜单是使用挖空绑定动态生成的 -
$(function() {
$("#menu a").click(function(){
$("#menu a").removeClass('active');
$(this).addClass('active');
});
ko.applyBindings();
});
<ul id="menu" data-bind="foreach: menuItem">
<li>
<a data-bind="text: menuText"></a>
</li>
</ul>
单击事件不会附加到这些项,因为 ko.applyBindings 发生在 dom ready 上。 我知道有一些像 afterRender 这样的事件可以用来解决这个问题,但使用 ViewModel 似乎更干净 -
<ul data-bind="foreach: menuItem">
<li>
<a data-bind="text: menuText,
click:setActive, css: {active: someComputed }"></a>
</li>
</ul>
使用 MVVM 模式执行此操作的正确方法是什么?或者敲除的正确方法是什么?通过视图模型似乎是最干净的,但它在哪里停止?您是否有javascript将其作为ViewModel中鼠标悬停时的下拉菜单?
我会向菜单项添加一个 isSelected 可观察对象,然后在单击菜单项时切换它(使用单击绑定)。然后,您可以在将使用isSelected的视图中使用css绑定。
正如您在使用挖空时所看到的,最好只与视图模型交互,而不是像使用 jQuery 那样与 dom 交互。
var ViewModel = function () {
var self = this;
self.menuItems = [
new MenuItem('Text1'),
new MenuItem('Text2'),
new MenuItem('Text3'),
new MenuItem('Text4')
];
self.toggleMenuItem = function (menuItem) {
for (var i = 0; i < self.menuItems.length; i++) {
self.menuItems[i].isSelected(false);
}
menuItem.isSelected(true);
};
};
var MenuItem = function (menuText) {
var self = this;
self.menuText = menuText;
self.isSelected = ko.observable(false);
};
<ul id="menu" data-bind="foreach: menuItems">
<li>
<a data-bind="text: menuText, click: $parent.toggleMenuItem, css: { active: isSelected }"></a>
</li>
</ul>
http://jsfiddle.net/d625vaad/1/