当用户选择一个菜单项时,我想添加这个项目活动类。
由于您使用的是 Ember 1.5,我将首先向您展示一些在旧版本中实现此目的的方法。
最简单的方法是向项目本身添加一个标志isActive,并将其用作css类的条件。您可以在selectMenuItem 操作中为单击的项目将标志设置为true。如果您的逻辑一次只允许一个项目处于活动状态,您还必须将任何当前活动项目的isActive 标志重置为false。
{{#each menuItem in sideMenuItems}}
<li {{bind-attr class="menuItem.isActive:active-class"}} {{action 'selectMenuItem' _view.contentIndex}}>
{{menuItem.text}}
</li>
{{/each}}
控制器:
Ember.ObjectController.extend({
sideMenuItems: // ... your array of items, each containing an isActive flag
actions: {
selectMenuItem: function(itemIndex) {
var items = this.get('sideMenuItems');
items.forEach(function(item, idx) { // go through the items,
if(idx === itemIndex) { // find the clicked item and set it as active
Ember.set(item, 'isActive', true);
} else { // reset all other items
Ember.set(item, 'isActive', false);
}
});
}
}
})
一种更有效的方法是将当前活动的项目存储为一个单独的变量,这将消除对 sideMenuItems 数组进行两次迭代的需要:
控制器:
Ember.ObjectController.extend({
sideMenuItems: // ... your array of items, each containing an isActive flag
activeMenuItem: null,
actions: {
selectMenuItem: function(itemIndex) {
var items = this.get('sideMenuItems');
var currActive = this.get('activeMenuItem');
var nextActive = items.objectAt(itemIndex);
// if there is a currently active item, deactivate it
if(currActive) {
Ember.set(currActive, 'isActive', false);
}
// if the user clicked on the currently active item, we just reset the selected item
// otherwise we update the isActive flag for the clicked item
if(currActive === nextActive) {
nextActive = null;
} else {
Ember.set(nextActive, 'isActive', true);
}
// set the clicked item as the currently active menu item
this.set('activeMenuItem', nextActive);
}
})
另一种方法是创建一个自定义组件menu-item,它根据活动索引呈现您的li 项,有无类。
Ember.Component.extend({
// passed in
activeIndex: -1,
index: -1,
selectMenuItemAction: '',
// local
tagName: 'li',
classNameBindings: ['activeClass'],
activeClass: function() {
var idx = this.get('index');
var activeIdx = this.get('activeIndex');
// if the current item is the active index, return the active class
if(idx === activeIdx) {
return 'active-class';
}
// otherwise return no class
return '';
}.property('activeIndex')
actions: {
selectMenuItem: function() {
this.sendAction('selectMenuItemAction', this.get('index'));
}
}
})
然后像这样使用它:
{{#each menuItem in sideMenuItems}}
{{#menu-item index=_view.contentIndex activeIndex=selectedMenuIndex selectMenuItemAction="selectMenuItem"}}
{{menuItem.text}}
{{/menu-item}}
{{/each}}
控制器:
Ember.ObjectController.extend({
selectedMenuIndex: 0,
actions: {
selectMenuItem: function(itemIndex) {
this.set('selectedMenuIndex', itemIndex);
}
}
})
由于使用 _view.contentIndex 有点像 hack,您可以只传递实际的菜单项,然后比较对象引用而不是索引来确定活动项:
菜单项组件:
Ember.Component.extend({
// passed in
activeItem: null,
item: null,
selectMenuItemAction: '',
// local
tagName: 'li',
classNameBindings: ['activeClass'],
activeClass: function() {
var item = this.get('item');
var activeItem = this.get('activeItem');
// if the current item is the active item, return the active class
if(item === activeItem) {
return 'active-class';
}
// otherwise return no class
return '';
}.property('activeItem')
actions: {
selectMenuItem: function() {
this.sendAction('selectMenuItemAction', this.get('item'));
}
}
})
然后像这样使用它:
{{#each menuItem in sideMenuItems}}
{{#menu-item item=menuItem activeItem=selectedMenuItem selectMenuItemAction="selectMenuItem"}}
{{menuItem.text}}
{{/menu-item}}
{{/each}}
控制器:
Ember.ObjectController.extend({
selectedMenuItem: null,
actions: {
selectMenuItem: function(item) {
this.set('selectedMenuItem', item);
}
}
})
这是在 Ember > 1.13 中执行此操作的一种更简单的方法
Ember > 1.13 支持内联助手,因此您可以按照自己的意愿实现这一点。 Ember CLI 1.13 还附带了babel,因此我们也可以使用 ES6,从而进一步简化:
控制器:
Ember.Controller.extend({
selectedMenuIndex: 0,
menuItems: // ...
actions: {
selectMenuItem(itemIndex) {
this.set('selectedMenuIndex', itemIndex);
}
}
});
模板:
{{#each menuItems as |item index|}}
<li class="{{active-class index selectedMenuIndex}}" {{action "selectMenuItem" index}}>
{{item.text}}
</li>
{{/each}}
助手:
activeClass(params) {
const [ index, active ] = params; // use ES6 destructuring
return (index === active) ? 'active-class': '';
}
Here is a working twiddle