Я использую 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>
Тем не менее, я чувствую, что такой подход создания вложенного меню не является хорошим, потому что предположим, что если я хочу программно программировать, то с его подходом это невозможно?
Может ли кто-нибудь предложить мне хороший подход к решению такого рода сценариев?
Вчера я столкнулся с подобным сценарием. Вы можете взглянуть на мое решение. Есть ли какой-либо плагин для нокаута для отображения вложенного контекстного меню? , Главное, что я использовал привязку шаблона, чтобы иметь возможность создавать иерархическое меню любой глубины.
Убедитесь, что каждый элемент меню имеет уникальный идентификатор. Для примера данных, которые вы дали name
будет достаточно, но вам, возможно, придется добавить свойство fullPath
к моделям просмотра элементов меню.
Функция goToMenu
теперь может принимать только один параметр: uniqueMenuIdentifier
и рекурсивно 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">
Смотрите эту скрипту для демонстрации.
Из этого вы также можете догадаться, что даже можно установить chosenMenu
напрямую:
// No longer needed:
//function findMenuItem(menuList, uniqueMenuIdentifier) { }
self.goToMenu = function (menuItem) {
self.chosenMenu(menuItem);
}
Смотрите эту скрипту для демонстрации.
$root.goToMenu($parent, $data);
Вы также можете добавить какой-то уникальный идентификатор к каждому пункту меню (если у него его еще нет). Это может упростить поиск и выбор пунктов меню.