コード コメント付きの JSFiddle デモ
ビューには、避けたいと思われる DOM トラバーサルが少しあります...この例は非常に小さいため、ユーザー エクスペリエンスを台無しにすることはありませんが、ベスト プラクティスであり、すべての優れた機能です。
これはあなたにとって良い出発点/例になるはずです。
変数設定
var MenuView
, MenuItemView
, MenuItemModel
, menu //MenuView Instance
, menuItem //MenuItemView Instance
;
MenuItemModel
MenuItemModel = Backbone.Model.extend({
'defaults': {
'url': undefined
, 'text': undefined
}
});
メニュービュー (<ul>)
MenuView = Backbone.View.extend({
'tagName': 'ul'
, 'id': 'MenuView'
, 'menuItems': []
, 'activeButton': undefined
, 'initialize': function ( menuObjJSON, parent ) {
var menuItem;
for ( menuItemIndex in menuObjJSON ) {
this.addMenuItem( new MenuItemModel(menuObjJSON[menuItemIndex]) )
}
this.render(parent);
}
, 'render': function ( parent ) {
$(parent).append(this.$el);
}
, 'addMenuItem': function ( model ) {
var menuItem = new MenuItemView({
'model': model,
'parentElement': this.$el
});
menuItem.on('changeActive', this.setActiveButton, this);
this.menuItems.push( menuItem );
return menuItem;
}
, 'removeMenuItem': function ( identifier ) {
var i, menuItem, length = this.menuItems.length, menuItemsCopy;
for (i = 0; i < length; i++) {
if ( this.menuItems[i] ) {
menuItemView = this.menuItems[i];
if ( menuItemView.model.get('text').toLowerCase() === identifier.toLowerCase()
|| menuItemView.model.get('url').toLowerCase() === identifier.toLowerCase() )
{
menuItemView.destroy();
debugger;
menuItemsEnd = this.menuItems.slice(i+1, length);
this.menuItems = [].concat(this.menuItems.slice(0,i), menuItemsEnd);
return true;
}
}
}
return false; //if menu item not found
}
, 'setActiveButton': function ( activeMenuItem ) {
if ( this.activeButton ) {
this.activeButton.removeHighlight();
}
this.activeButton = activeMenuItem;
}
});
MenuItemView (<li>)
MenuItemView = Backbone.View.extend({
'tagName': 'li'
, 'className': 'menuItem'
, 'events': {
'click a': 'highlight'
}
, 'initialize': function ( options ) {
this.render(options.model, options.parentElement);
}
, 'render': function ( model, parentElement ) {
this.$el.append("<a href='" + model.get('url')+ "'>" + model.get('text') + "</a>");
parentElement.append(this.$el);
}
, 'highlight': function ( event ) {
if ( !this.$el.hasClass('active') ) {
this.trigger('changeActive', this);
this.$el.addClass('active');
}
}
, 'removeHighlight': function () {
this.$el.removeClass('active');
}
, 'destroy': function () {
this.unbind('click a');
this.remove(); //unbind from DOM, remove DOM events
}
});
メニューのインスタンス化
menu = new MenuView([
{'url': '#home', 'text': 'Home'}
, {'url': '#catpics', 'text': 'Cat Pics'}
, {'url': '#dogpics', 'text': 'Dog Pics'}
, {'url': '#about', 'text': 'About Us'}
], $('body'));
新しいメニュー項目の追加。(最も実用的な例ではありませんが、出発点です)
setTimeout(function(){
menu.addMenuItem({'url': '#contact', 'text': 'Contact Us'});
}, 1000);
setTimeout(function(){
menu.addMenuItem({'url': '#Login', 'text': 'Log In'});
}, 2000);
setTimeout(function(){
menu.addMenuItem({'url': '#W3bm4573r', 'text': 'W3bm4573r'});
}, 3000);
setTimeout(function(){
menu.addMenuItem({'url': '#something', 'text': 'Something'});
}, 4000);
メニュー項目の削除 (最も実用的な例ではありませんが、出発点です)
setTimeout(function(){
menu.removeMenuItem('#contact');
}, 5000);
setTimeout(function(){
menu.removeMenuItem('about us');
}, 5000);
setTimeout(function(){
menu.removeMenuItem('#SOMETHING');
}, 5000);