angular2/rxjs/redux 重新实现 - 路由更改与 observable 混淆

angular2/rxjs/redux reimplementation - route change messing with observable

我正在尝试在 angular2 应用程序的 rxjs 中对 redux 进行基本的重新实现。

此时基本上只是我在互联网上找到的一些东西拼接在一起,this plunker for angular DI, this for file structure, this for combineReducers and lastly this for "redux in rxjs"

我遇到了几个问题,但这是目前最大的问题: https://www.youtube.com/watch?v=xXau87UmqOs

发生了什么:

这是我在 console.log 中描述的内容(也可以在 youtube 视频中看到)

---- index loaded ----
index.js:33 map in index: Object {todos: Array[3]}
index.js:35 resp in index: Object {todos: Array[3]}
index.js:38 ---- index destroyed ----
todos.js:31 ---- todos loaded ----
todos.js:33 map in todos: Object {todos: Array[3]}
todos.js:35 resp in todos: Object {todos: Array[3]}
todos.js:45 ---- todos destroyed ----
index.js:30 ---- index loaded ----
index.js:33 map in index: Object {todos: Array[3]}
index.js:35 resp in index: Object {todos: Array[3]}
index.js:38 ---- index destroyed ----
todos.js:31 ---- todos loaded ----
todos.js:33 map in todos: Object {todos: Array[3]}
todos.js:35 resp in todos: Object {todos: Array[3]}
NgStore.js:49 Object {type: "DELETE_TODO", id: 1}
todos.js:33 map in todos: Object {todos: Array[2]}
todos.js:35 resp in todos: Object {todos: Array[2]}
todos.js:45 ---- todos destroyed ----
index.js:30 ---- index loaded ----
index.js:33 map in index: Object {type: "DELETE_TODO", id: 1}
index.js:35 resp in index: Object {type: "DELETE_TODO", id: 1}

知道什么会导致 observable 在路由改变时发生改变吗?

这是 repo https://github.com/fxck/ng2-rx-redux 它使用最新的 alpha(46)

您不需要在 rxjs 中实现 redux,因为它已经在那里实现了。 Observable::scan(accumulator, [seed]) operator does exactly the same what redux does. Here's a simplified example (see this plunk):

// store.js
import BehaviorSubject from '@reactivex/rxjs/dist/cjs/subjects/BehaviorSubject';
import reducer from './reducer';
export default new BehaviorSubject().scan(reducer, 0)

// reducer.js
export default function(state, action) {
  switch (action && action.type) {
    case 'INCREMENT':
      return state + 1;
    case 'DECREMENT':
      return state - 1;
    default:
      return state;
  }
}

// app.js
import {Component} from 'angular2/angular2'
import store from './store';

@Component({
  selector: 'my-app',
  template: `
    <h2>{{ value }}</h2>
    <button (click)="increment()">Increment</button>
    <button (click)="decrement()">Decrement</button>
  `
})
export class App {
  constructor() {
    store.subscribe(value => this.value = value);
  }

  increment() { store.next({ type: 'INCREMENT' }) }
  decrement() { store.next({ type: 'DECREMENT' }) }
}

嗯,当然你可以重新发明轮子(至少只是为了好玩)。

暗中拍摄。路线更改是视图状态的更改。我敢打赌 angular2 会重新创建或更新您在路由器中配置的组件。您所描述的是:

  • 路线改变但模型没有改变:OK
  • 待办事项模型中的路线更改和状态更改会给您错误的结果。

我在 Angular 中的经验是零,但从我读到的内容来看,我的直觉是:

  • 如果状态没有变化,路由器不会更新组件(不需要,因为它们只依赖于没有变化的状态,对吧?)
  • 如果状态发生变化,则路由器会要求更新受影响的组件。因为你取回了最后一个 redux 动作,并且你使用了一个行为主题,我盲目猜测可能是你一直保持主题活跃,并在路由更改时重新订阅,当你重新订阅时,你取回了最后一个价值(这是行为主体根据规范所做的)。

这完全是一团糟,但你应该尝试在这些线上进行测试,至少要排除这种可能性。

您使用 RxJS API 不正确。要修复您的代码,您应该做接下来的两件事:

  1. 将初始状态设置为 scan 运算符。
// services/NgStore.ts

this._subject = new BehaviorSubject().scan(rootReducer, initialState);
  1. 更改 switch 语句中的条件以检查 action 是否为空(例如 === undefined):
// reducers/todo.ts

export const todos = (state = [], action) => {
  switch(action && action.type) {
    // ...
  }
};

PS 对于不知道 redux 已经在 RxJS 中实现的人,我不会删除我的第一个答案。