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

Avoid image reload on state update

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

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" 属性 上的图像正常加载。

当我从我的 sidenav 中点击一个项目时,状态会更新:

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

我的问题是当我更新 "menuItems" 状态时 "logo-image" 再次重新加载。当图像再次加载时,我在屏幕上看到了一点 "blink"。

这是我的 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);
    }
  }
}

我是否没有正确更新状态,或者此行为有解决方法?

我认为这里的问题是您的模板正在重新加载整个列表中的每一项您想要 select 一个项目 - 因为您正在调用 setState,这将导致任何订阅您的状态接收更新。

我建议以不同的方式为您的状态建模,例如

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.

绑定一个样式

这样当项目为 selected/unselected.

时,您不会修改列表