我在我的项目中使用knockoutjs。我有一个场景,我必须在我的viewmodel中创建一个嵌套菜单,我这样做:
self.menu = [
{
name: 'Services',
sub: [{ name: 'Service-A' }, { name: 'Service-B' }]
},
// etc
];
self.chosenMenu = ko.observable();
self.goToMenu = function (main, sub) {
var selectedMenu = {
main: main,
sub: sub
};
self.chosenMenu(selectedMenu);
};
我的观点:
<ul class="nav navbar-nav menuitems col-md-8" data-bind="foreach: menu">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<span data-bind="text: name"></span></a>
<ul class="dropdown-menu" role="menu" data-bind="foreach: sub">
<li>
<a href="javascript:void(0);" data-bind="text: name,
click: function() { $root.goToMenu($parent, $data); }">
</a>
</li>
</ul>
</li>
</ul>
但是,我觉得这种创建嵌套菜单的方法并不好,因为如果我想以编程方式继续使用任何菜单项,那么他的方法是不可能的?
有人可以建议我处理这种情况的好方法吗?
答案 0 :(得分:0)
确保每个菜单项都有唯一标识符。对于您已经提供name
的示例数据就足够了,但您可能需要向菜单项视图模型添加fullPath
属性。
您的goToMenu
函数现在只能使用一个参数:uniqueMenuIdentifier
,并递归所有菜单项以找到正确的参数,如下所示:
function findMenuItem(menuList, uniqueMenuIdentifier) {
for (var i = 0; i < menuList.length; i++) {
if (menuList[i].name === uniqueMenuIdentifier) {
return menuList[i];
}
if (!!menuList[i].sub) {
var subItem = findMenuItem(menuList[i].sub, uniqueMenuIdentifier);
if (!!subItem) {
return subItem;
}
}
}
return null;
}
self.goToMenu = function (menuItem) {
var uniqueMenuIdentifier = menuItem.name;
var item = findMenuItem(self.menu, uniqueMenuIdentifier);
self.chosenMenu(item);
}
这允许在锚标记中进行更简单的绑定:
<a href="javascript:void(0);" data-bind="text: name, click: $root.goToMenu">
请参阅this fiddle了解演示。
从这里你也可以猜到甚至可以直接设置chosenMenu
:
// No longer needed:
//function findMenuItem(menuList, uniqueMenuIdentifier) { }
self.goToMenu = function (menuItem) {
self.chosenMenu(menuItem);
}
请参阅this fiddle了解演示。
答案 1 :(得分:0)
昨天我遇到了类似的情况。您可以查看我的解决方案 Is there any knockout plugin for showing a nested context menu?。重点是我使用模板绑定能够构建任何深度的分层菜单。