假设您从一个通过jquery完成UI影响的网站开始。例如a,菜单。单击锚点将对此应用类以显示锚点是活动锚点。这是在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准备就绪时发生。我知道像AfterRender这样的事件可以用来解决这个问题,但使用ViewModel看起来更干净 -
<ul data-bind="foreach: menuItem">
<li>
<a data-bind="text: menuText,
click:setActive, css: {active: someComputed }"></a>
</li>
</ul>
使用MVVM模式执行此操作的正确方法是什么?或者用淘汰赛做这个的正确方法是什么?通过viewmodel似乎是最干净的,但它在哪里停止?你有没有javascript使它成为ViewModel中鼠标悬停的下拉菜单?
答案 0 :(得分:1)
我会在菜单项中添加一个isSelected observable,然后在单击菜单项时切换(使用单击绑定)。然后你可以在视图中使用css绑定,它将使用isSelected。
正如您所看到的,当您使用knockout时,最好只与视图模型交互,而不是像使用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>