避免在状态更新时重新加载图像

时间:2019-05-09 22:27:50

标签: angular state-management ngxs

我正在使用NGXS作为状态管理器。 我有一个填充“ sidenav”组件的“ menuItems”对象:

export const menuItems: Array<MenuItem> = [


{
    icon: 'assets/circle-logo.png',
    label: 'Home',
    route: '/home',
    selected: false
  },
  {
    icon: 'assets/circle-logo.png',
    label: 'Customers',
    route: '/customers',
    selected: false
  },
  {
    icon: 'assets/circle-logo.png',
    label: 'Entries',
    route: '/entries',
    selected: false
  }];

当应用程序首次加载“ icon”属性上的图像时,会正常加载。

enter image description here

当我从sidenav单击一个项目时,状态就会更新:

enter image description here

然后将索引发送到状态,以将选择的属性更改为“ true”并突出显示该项目,如上图所示。

我的问题是,当我更新“ menuItems”状态时,将再次重新加载“徽标图像”。再次加载图像时,我在屏幕上看不到一点“闪烁”。

enter image description here

这是我的sidenav状态的代码:

import { State, Action, StateContext } from '@ngxs/store';
import { MenuItem } from '@shared/types';
import { menuItems } from '@components/sidenav/menu-items';

export class SelectMenuItem {
  static readonly type = 'SelectMenuItem';
  constructor(public itemIndex: number) {}
}

@State<Array<MenuItem>>({
  name: 'menuItems',
  defaults: menuItems
})
export class SideNavState {
  @Action(SelectMenuItem)
  selectMenuItem(ctx: StateContext<Array<MenuItem>>, action: SelectMenuItem) {
    const { getState, setState } = ctx;
    const { itemIndex } = action;
    const state = getState();
    const currentItem = state.findIndex(s => s.selected);

    if (currentItem !== itemIndex) {
      const newState = state.map((item, index) => {
        if (currentItem > -1 && currentItem === index) {
          item = { ...item, selected: false };
        }
        if (itemIndex === index) {
          item = { ...item, selected: true };
        }
        return item;
      });
      setState(newState);
    }
  }
}

我无法正确更新状态,还是有解决此问题的方法?

1 个答案:

答案 0 :(得分:1)

我认为这里的问题是您的模板正在重新加载要选择项目的每个项目的整个列表-因为您正在调用setState,这将导致订阅您状态的任何人都收到更新。< / p>

我建议您以其他方式对您的状态进行建模,例如

export class SelectMenuItem {
  static readonly type = 'SelectMenuItem';
  constructor(public itemIndex: number) {}
}

// In the state model, capture the selected item/index
// separate from the list of menu items.
interface MenuItemStateModel { 
  selectedItem: number,
  menuItems: MenuItem[]
}

@State<MenuItemStateMode>({
  name: 'menuItems',
  defaults: {
    selectedItem: null,
    menuItems: []
  }
})
export class MenuItemState { 

  @Action(SelectMenuItem)
  selectItem({patchState}: StateContext<MenuItemStateModel>, action: SelectMenuItem) { 
    patchState({selectedItem: action.itemIndex});
  }

  // .. Load the menu items from API (or hardcoded?)

}

然后从menuItem类型中删除“ selected”属性。在模板中,如果您随后要突出显示它,则可以根据itemIndex === state.selectedItem是否绑定样式。

这样,当您选择/取消选择项目时,您无需修改​​列表。