3

我正在使用 Angular 2 和@ngrx/store.question 开发一个关于良好实践以及如何做到这一点的项目。

我开发了一个“网络查找器”来管理文件。所以我可以做一些基本的动作,比如复制、移动等。

我不会解释原因,因为这只是一个示例,但移动文件包含 3 个步骤:

  • 逻辑:做一些验证。
  • 发送一个动作 A
  • 发送一个动作 B

这 3 个步骤是在我的角度组件内完成的。我已经考虑过了,我认为简单地调度一个执行一些验证的动作并调度其他 2 个动作是一个更好的主意。

我为什么要这样做?首先,它更容易阅读

this._store.dispatch(copy(myFile));

而不是

// ...
// verifications
// ...

this._store.dispatch(action1(myFile, foo, bar));
this._store.dispatch(action2(myFile));

其次,我可以copy即时调度我的动作创建者而不会遇到任何副作用,因为验证将在动作内部执行。

实际上,我可以在不进行验证的情况下发送我的action1et 。action2

最后,我所有的逻辑都在我的行动中。我可以让我的组件保持简单并专注于他们的工作(管理 UI 等)。这是伟大的。

问题1:好的做法?

这样做是个好主意吗?我想是的,但你的经历让我很感兴趣。

问题2:如何?

怎么做 ?我的动作创建者只是函数。我不能用 来装饰它们Injectable并使用constructor来注入实例。

以下是动作创建者的示例:

import { Action } from '@ngrx/store'

export const NAVIGATE_TO_NODE:string = '[Browser] Navigate to node';
export const ADD_TO_SELECTION:string = '[Browser] Add to browser selection';
export const REMOVE_FROM_SELECTION:string = '[Browser] Remove from browser selection';
export const REMOVE_ALL_FROM_SELECTION:string = '[Browser] Remove all from browser selection';

export const navigateToNode:(nodeId: number, paneId?: number)=>Action = (nodeId: number, paneId?: number) => {
  return {
    payload: { nodeId, paneId },
    type: NAVIGATE_TO_NODE
  };
};
export const addToSelection: (addInfo: any)=>Action = (addInfo: any) => {
  return {
    payload: addInfo,
    type: ADD_TO_SELECTION
  };
};
export const removeFromSelection: (removeInfo: any[])=>Action = (removeInfo: any[]) => {
  return {
    payload: removeInfo,
    type: REMOVE_FROM_SELECTION
  }
};
export const removeAllFromSelection: ()=>Action = () => {
  return {
    payload: null,
    type: REMOVE_ALL_FROM_SELECTION
  }
};

我怎样才能从那些动作创建者那里分派?

我已经使用 redux 作为 Redux 与 React 的实现,并且我创建了一个小包,允许我从动作创建者调度:redux-thunk

4

2 回答 2

3

我将第二个有线程序员的建议看一下 ngrx 示例应用程序。它展示了如何构建动作、reducers 和效果。

这是可注入动作类的示例。

@Injectable()
export class BookActions {
  static SEARCH = '[Book] Search';
  search(query: string): Action {
    return {
      type: BookActions.SEARCH,
      payload: query
    };
  }

然后在你的组件中......

constructor(private store: Store<AppState>, private bookActions: BookActions) {}

search(query: SearchOutput) {
  this.store.dispatch(this.bookActions.search(query));
}

以这种方式接近它。Reducers 应该是没有副作用的纯函数。因此,例如,要移动文件,您可以调度一个启动事务的操作,该操作可以使用文件名、目标和所需的任何其他操作细节来设置状态。该函数将返回新状态。将此减速器称为 START_MOVE。

在您的效果中,注意 START_MOVE,获取包含交易详细信息的状态,然后执行交易的第一部分。完成后,将具有更新状态的操作分派给 MOVE_2 或更具描述性的内容。

这个 reducer 使用下一步所需的详细信息设置状态,然后返回它。

效果监视 MOVE_2,然后执行事务的第二阶段。完成后,调度 MOVE_3。作为一个函数,它只是为第三部分设置状态,效果获取详细信息并完成交易。完成后,调度 MOVE_SUCCESS 以使用新文件名或其他设置状态。

如果出现错误,则流程中的任何点都可以分派 MOVE_ERROR,并以类似的方式进行处理,以进行清理或返回初始状态。或 MOVE_CANCEL 如果需要。

组件可以观察状态并将状态更新给用户。

于 2016-07-08T02:32:33.240 回答
2

很抱歉简短,但我只是略过您的问题,这只是对其中一部分的回应。如果你想让你的动作创建者可注入,那么将它们包装在一个类中。您可以从链接到 ngrx/store 的自述文件的 ngrx 示例应用程序中获得一些关于结构的优秀想法。我正在创建一个项目,在该项目中我为动作创建者模仿了他们的设置。

https://github.com/ngrx/example-app/tree/master/src/actions

于 2016-07-07T14:57:41.423 回答