代码之家  ›  专栏  ›  技术社区  ›  AlexNasonov

Angular+ngrx:如何在路由器url遍历时保持存储状态?

  •  2
  • AlexNasonov  · 技术社区  · 7 年前

    我知道每次用户刷新页面时,存储都会重置(所谓的“硬刷新”),但我希望当用户使用angular router遍历页面时,存储会保持不变。但是,正如我所看到的,它无论如何都会重置。

    我错了吗?是否有任何方法可以在不保存到本地存储或使用其他黑客的情况下保持存储?

    应用程序。单元ts

        import { NgModule } from '@angular/core';
        import { CommonModule } from '@angular/common';
        import { HttpClientModule } from '@angular/common/http';
        import { BrowserModule } from '@angular/platform-browser';
        import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
    
        // Routing
        import { AppRoutingModule } from './app-routing.module';
    
        // Ngrx
        import { StoreModule } from '@ngrx/store';
        import {
          StoreRouterConnectingModule,
          RouterStateSerializer,
        } from '@ngrx/router-store';
        import { StoreDevtoolsModule } from '@ngrx/store-devtools';
        import { EffectsModule } from '@ngrx/effects';
    
        // Other
        import { reducers, metaReducers } from './core/reducers';
        import { CustomRouterStateSerializer } from './core/utils/router.utils';
        import { MaterialModule } from './material/material.module';
    
        // Environment
        import { environment } from '../environments/environment';
    
        // Components
        import { AppComponent } from './app.component';
        import { NotFoundComponent } from './core/components/not-found.component';
        import { NotAuthorizedComponent } from './core/components/not-authorized.component';
        import { HomeComponent } from './core/components/home.component';
        import { UsersModule } from './users/users.module';
        import { EventsModule } from "./events/events.module";
    
        @NgModule({
          declarations: [
            AppComponent,
            NotFoundComponent,
            HomeComponent,
            NotAuthorizedComponent,
          ],
          imports: [
            CommonModule,
            HttpClientModule,
            BrowserModule,
            BrowserAnimationsModule,
            AppRoutingModule,
            MaterialModule,
            StoreModule.forRoot(reducers, { metaReducers }), 
            StoreRouterConnectingModule.forRoot({stateKey: 'router'}),
            StoreDevtoolsModule.instrument(),
            EffectsModule.forRoot([]),
            UsersModule,
            EventsModule
    
      ],
      providers: [
        { provide: RouterStateSerializer, useClass: CustomRouterStateSerializer },
      ],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
    

    ./堆芯/减速器/索引。ts

    import {
      ActionReducerMap,
      ActionReducer,
      MetaReducer, createFeatureSelector, createSelector,
    } from '@ngrx/store';
    import { environment } from '../../../environments/environment';
    import { RouterStateUrl } from '../utils/router.utils';
    import * as fromRouter from '@ngrx/router-store';
    import * as fromAuth from '../../users/reducers/auth.reducer';
    
    import { storeFreeze } from 'ngrx-store-freeze';
    
    export interface State {
      router: fromRouter.RouterReducerState<RouterStateUrl>,
      auth: fromAuth.State;
    }
    
    export const reducers: ActionReducerMap<State> = {
      router: fromRouter.routerReducer,
      auth: fromAuth.reducer
    };
    
    export function logger(reducer: ActionReducer<State>): ActionReducer<State> {
      return function(state: State, action: any): State {
        console.log('state', state);
        console.log('action', action);
    
        return reducer(state, action);
      };
    }
    
    export const metaReducers: MetaReducer<State>[] = !environment.production
      ? [logger, storeFreeze]
      : [];
    
    // AUTH reducers
    export const selectAuthState = createFeatureSelector<fromAuth.State>('auth');
    
    export const getUser = createSelector(
      selectAuthState,
      fromAuth.getUser
    );
    export const getLoaded = createSelector(
      selectAuthState,
      fromAuth.getLoaded
    );
    export const getError = createSelector(
      selectAuthState,
      fromAuth.getError
    );
    

    其思想是通过HTTP get从服务器获取用户凭据,将其放入存储区,然后从存储区而不是服务器获取。所以我有一个警卫:

    @Injectable()
    export class AuthGuard implements CanActivate {
    
      constructor(private store: Store<State>, protected router: Router) {
      }
    
      protected getFromStoreOrAPI(): Observable<any> {
        return this.store
          .select(getUser)
          .do(user => {
            if (!user) this.store.dispatch(new Signin());
          })
          .filter(user => user)
          .take(1);
      }
    
      canActivate(): Observable<boolean> {
        return this.getFromStoreOrAPI()
          .switchMap(() => Observable.of(true))
          .catch(() =>  Observable.of(false));
      }
    }
    

    在…上 this.store.dispatch(new Signin()); 它进行HTTP调用并将数据放入存储区。

    问题是,每次用户转到新页面时,它都会进行HTTP调用。

    2 回复  |  直到 7 年前
        1
  •  3
  •   AlexNasonov    7 年前

    我真蠢!习惯于 <a href="/link">Link</a> 而不是 <a routerLink="/link">Link</a> !

        2
  •  1
  •   Christian    7 年前

    检查减速机,我确信您犯了一个错误,忘记在switch语句中返回状态:

    switch(action.type){
           ...
            default:
                return state;
    }