编辑-如果我将redux-state-sync配置为使用localstorage,那么这一切都可行。我制作了一个包含工作代码示例的存储库https://bitbucket.org/em-aitch/sync-app/src/master/。如果广播频道类型(app.component.ts:76)从'localstorage'更改为'native',则绑定(@select和{{property}}都不再起作用!
EDIT2-问题How to find out what breaks Angular binding?回答了这个问题
我已使用下面所述的redux-state-sync进行了设置。 Redux状态更改已同步到其他浏览器窗口,但@select不起作用。
当我登录一个窗口时,会出现app-nav-menu,因为ngIf评估为true。同样,两个预订都将写入控制台:
new login state = true app.component.ts:20
subsribed to local observable : true app.component.ts:24
但是,即使在另一个窗口中完成的登录状态更改已在那里同步,其他浏览器窗口也无法以相同的方式工作。控制台输出是相同的:
new login state = true app.component.ts:20
subsribed to local observable : true app.component.ts:24
但是问题是app-nav-menu没有出现。下面首先是与此代码直接相关的代码,最后是redux定义。
app.component.html
<body>
<app-nav-menu *ngIf="(isLoggedIn | async)"></app-nav-menu>
<div class="container">
<router-outlet></router-outlet>
</div>
</body>
app.component.ts
export class AppComponent {
title = 'app';
@select((state: IApplicationState) => state.login.isLoggedIn) isLoggedIn: Observable<boolean>;
subscription;
constructor(private ngRedux: NgRedux<IApplicationState>) {
this.subscription = this.ngRedux.select<ILoginState>('login')
.subscribe(newState => {
console.log('new login state = ' + newState.isLoggedIn);
});
this.isLoggedIn.subscribe(newState =>
console.log('subsribed to local observable : ' + newState));
}
}
app.module.ts
import { createStateSyncMiddleware, initStateWithPrevTab } from 'redux-state-sync';
import { Store, createStore, applyMiddleware } from 'redux';
export const store: Store<IApplicationState> = createStore(
rootReducer,
applyMiddleware(createStateSyncMiddleware())
);
export class AppModule {
constructor(ngRedux: NgRedux<any>) {
ngRedux.provideStore(store);
initStateWithPrevTab(store);
}
}
store / index.ts
import { combineReducers } from 'redux'
import { ILoginState, loginReducer } from './login'
import { withReduxStateSync } from 'redux-state-sync'
export interface IApplicationState {
login: ILoginState;
}
export const INITIAL_STATE : IApplicationState = {
login : { isLoggedIn: false, tokenInfo : null }
}
const appReducer = combineReducers<IApplicationState>({
login: loginReducer
})
export const rootReducer = withReduxStateSync(appReducer);
就像我在顶部的编辑中说的那样。如果我将其配置为使用localstorage,则此方法有效:
applyMiddleware(createStateSyncMiddleware(
{ broadcastChannelOption: { type: 'localstorage' } })));
答案 0 :(得分:1)
如果状态已经同步,则可能不是redux-state-sync问题,我想帮助您解决问题,但是,我对Angular和@select的了解有限。
但是我可以与您分享Redux-state-sync如何在浏览器标签之间同步数据。
const getIniteState = () => ({ type: GET_INIT_STATE });
const sendIniteState = () => ({ type: SEND_INIT_STATE });
const receiveIniteState = state => ({ type: RECEIVE_INIT_STATE, payload: state });
在第一个选项卡之后打开的选项卡会将GET_INIT_STATE操作分派到另一个选项卡的存储中,一旦他们收到此操作,它们将分派SEND_INIT_STATE以及现有状态。同时,您最后打开的标签页会收到此SEND_INIT_STATE事件以及其他标签页的整个状态,并使用该状态触发RECEIVE_INIT_STATE。
基本上,withReduxStateSync将侦听RECEIVE_INIT_STATE操作,并将整个状态替换为该操作的有效负载。
export const withReduxStateSync = appReducer =>
((state, action) => {
let initState = state;
if (action.type === RECEIVE_INIT_STATE) {
initState = action.payload;
}
return appReducer(initState, action);
});
据我所见,您面临的问题可能是可观察到的问题,即未检测到状态的任何变化,因此不会触发更新。
希望这会有所帮助,对不起,我无法为您提供更多有用的建议。如果您需要我提供更多信息,请告诉我,如果您解决了此问题,也请告诉我。 ;-)