首页 > 解决方案 > 角度路由问题

问题描述

我已经定义了我的角度路由,以在用户未登录时重定向到登录页面,但每次我强制关闭浏览器并通过 localhost:4200/ 重新访问我的角度应用程序时,我没有得到重定向并且我的应用程序显示空组件并且没有重定向。如果用户未使用 AuthGuard 登录,我将其设计为重定向到登录,但即使用户已登录,并且我可以在我的 localStorage 中看到应用程序数据,该页面或多或少几乎保持空白。我知道出了点问题,但我就是想不通。这是我的 app-routing.module.ts:

import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { SignupComponent } from './views/auth/signup/signup.component';
import { LoginComponent } from './views/auth/login/login.component';
import { ResetComponent } from './views/auth/reset/reset.component';
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
import { ErrorPageComponent } from './views/error-page/error-page.component';
import { ToastrModule } from 'ngx-toastr';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatButtonModule } from '@angular/material/button';
import { CommonModule } from '@angular/common';

const routes : Routes = [
  {
    path : '',
    redirectTo : '/login',
    pathMatch : 'full'
  },
  {
    path : 'login',
    component : LoginComponent
  },
  {
    path : 'signup',
    component : SignupComponent
  },
  {
    path : 'passwordreset',
    component : ResetComponent
  },
  {
    path : '**',
    component : ErrorPageComponent,
    data : { title : 'Page Not Found'}
  }
];

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    HttpClientModule,
    MatCheckboxModule,
    MatButtonModule,
    ReactiveFormsModule,
    RouterModule.forRoot(routes, {enableTracing : false, useHash : true}),
  ],
  exports: [RouterModule]
})
export class AppRoutingModule { }

这是我的登录组件:


import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { LoginValidator } from 'src/app/shared/util/validators/login.validators';
import { Title } from '@angular/platform-browser';
import { LoginService } from 'src/app/shared/services/login.service';
import { Router, ActivatedRoute } from '@angular/router';
import { ToastrService } from 'ngx-toastr';

@Component({
  selector: 'login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.scss'],
})
export class LoginComponent implements OnInit {
  /**
   * Page Title
   *
   * @var String
   */
  title = '';

  /**
   * Variable to check if animation class is needed
   *
   * @var Boolean
   */
  isShakeClassNeeded : Boolean = false;

  /**
   * A variable to check if the user checked the 'remember me' checkbox
   *
   * @var Boolean
   */
  isRememberChecked : Boolean = true;

  /**
   * Check if the form has been submitted
   *
   * @var Boolean
   */
  isFormSubmitted : Boolean;

  /**
   * If the form is invalid or contains invalid input
   *
   * @param Boolean
   */
  isFormInValid : Boolean = false;

  /**
   * If the login details provided are correct. This should be true
   * else display an error message
   *
   * @param Boolean
   */
  isLoginInValid : Boolean = false;

  /**
   * Whether the server return a 'Bad Request' error code
   *
   * @var Boolean
   */
  isBadRequestResponse : Boolean = false;

  /**
   * Whether the server returned a '404 Not Found' error code
   *
   * @var Boolean
   */
  isError404 : Boolean = false;

  /**
   * Loading animation
   * @var Boolean
   */
  loading : Boolean = false;

  /**
   * Login Form Using Reactive Form Approach
   */
  loginForm = new FormGroup({
    loginemail : new FormControl('', [Validators.required, Validators.email, LoginValidator.cannotContainSpaces]),
    loginpassword : new FormControl('', [Validators.required, Validators.minLength(6)])
  });

  /**
   * The previous page the user was at
   * @var string
   */
  returnUrl : string;

  /**
   * If the login button has been clicked, set this to true
   * @var Boolean
   */
  isLoginProgressing : Boolean = false;

  /**
   * Class Constructor
   *
   * @param None
   */
  constructor(
    private router : Router,
    private pageTitle : Title,
    private loginService : LoginService,
    private route : ActivatedRoute,
    private toastrService : ToastrService
    )
    {
      this.pageTitle.setTitle(this.title);
    }

    ngOnInit(): void {
      if(!localStorage.getItem('LoggedInUser')){
        this.loginService.logout();
        this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/login';
      }else
        this.router.navigate([this.returnUrl ? this.returnUrl : 'dashboard']);
    }

  /**
   * Handles form submission and login
   *
   * @param None
   */
  formSubmitted(){
    this.isFormSubmitted = true;
    this.isLoginProgressing = true;

    if(!this.loginForm.valid){
      this.isFormInValid = true;
      this.isShakeClassNeeded = true;
      this.isLoginProgressing = false;
    }else{
      this.loginService.login(this.email.value, this.password.value)
        .subscribe( response => {
          if(response){
            this.isLoginProgressing = false;
            let returnUrl = this.route.snapshot.queryParamMap.get('returnUrl')
            this.router.navigate([returnUrl || '/dashboard'])
          }else{
            this.isLoginInValid = true;
            this.isShakeClassNeeded = true;
            this.isLoginProgressing = false;
          }
        },
          error => {
            if(error.status == 400){
              this.isShakeClassNeeded = true;
              this.isBadRequestResponse = true;

              this.isLoginProgressing = false;
              this.toastrService.error('Something went wrong. Please check your connection', 'Login Error', {
                timeOut : 34000
              });
            }else if(error.status == 404){
              this.isShakeClassNeeded = true;
              this.isError404 = true;
              this.isLoginProgressing = false;
            }
          }
        );

    }
  }


  /**
   * Get the email from the formGroup control
   *
   * @param None
   */
  get email(){
    return this.loginForm.get('loginemail');
  }

  /**
   * Get the password from the formGroup control
   *
   * @param None
   */
  get password(){
    return this.loginForm.get('loginpassword')
  }

}

这是我的 AuthGuard:

import { LoginService } from './login.service';
import { Injectable } from '@angular/core';
import { CanActivate, Router, RouterStateSnapshot, ActivatedRouteSnapshot } from '@angular/router';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {

  /**
   *Class Constructor
   *
   * @param router
   */
  constructor(private router : Router, private loginService : LoginService) {}

   /**
    * Implements interface method: 'canActivate'
    */
   canActivate(route : ActivatedRouteSnapshot, state : RouterStateSnapshot){
      if(localStorage.getItem('LoggedInUser')){
        return true;
      }else{
      this.router.navigate(['/login'],
        { queryParams :
          {
            returnUrl : state.url
          }
        });
      }

      return false;
   }
}

这是我的 url 当前在积极处理项目并重新编译时的样子: 在此处输入图像描述

这是关闭浏览器并重新打开后的样子: 在此处输入图像描述

如果我以前登录过并且在我关闭浏览器而不登录之前位于类似:```localhost:4200/#/dashboard`` 的 url 中,我希望在我重新打开后 url 保持不变,因为只要localStorage中有用户数据。

我的 app.component.ts 看起来像这样:

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent{
  title = '';
}

由于该项目有一个管理面板,我在不同的模块中定义了子路由,并使用主路由模块(此处未包含)将它们链接到 app.module.ts。我不知道如何定位错误,因为 console.log() 上没有显示错误。请问我该如何解决这个问题,如果有任何意义的话。

这就是我使用 canActivate 和 AuthGuard 来保护我的后端仪表板和所有其他管理路由的方式:

import { AuthGuard } from 'src/app/shared/services/auth-guard.service';
import { DashboardComponent } from './dashboard.component';

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

const routes : Routes = [
  {
    path: '',
    component : DashboardComponent,
    canActivate : [AuthGuard]
  }
];

@NgModule({
  imports : [RouterModule.forChild(routes)],
  exports : [RouterModule]
})
export class DashboardRoutingModule{
}

这是列出我的组件的仪表板模块:

import { MatProgressBarModule } from '@angular/material/progress-bar'
import { MatTableModule } from '@angular/material/table';
import { DashboardRoutingModule } from './dashboard-routing.module';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { DashboardComponent } from './dashboard.component';
import { NgModule } from '@angular/core';
import {MatPaginatorModule} from '@angular/material/paginator'

@NgModule({
  declarations : [
    DashboardComponent
  ],
  imports: [CommonModule, MatProgressBarModule, MatPaginatorModule, MatTableModule, DashboardRoutingModule],
  exports : [RouterModule]
})
export class DashboardModule { }

这是我的后端布局模块,其中每个组件都连接到路由

import { RouterModule, Routes } from '@angular/router';
import { BackendLayoutComponent } from './backend-layout.component';
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AuthGuard } from 'src/app/shared/services/auth-guard.service';

const routes : Routes = [
  {
    path : '',
    component : BackendLayoutComponent,
    canActivate : [AuthGuard],
    children : [
      {
        path : 'dashboard',
        loadChildren : () => import('src/app/views/dashboard/dashboard.module').then(m => m.DashboardModule)
      },
      {
        path : 'brand',
        loadChildren : () => import('src/app/views/brand/brand.module').then(m => m.BrandModule)
      },
      {
        path : 'accounting',
        loadChildren : () => import('src/app/views/accounting/account.module').then(m => m.AccountModule)
      },
      {
        path : 'report',
        loadChildren : () => import('src/app/views/report/report.module').then(m => m.ReportModule)
      },
      {
        path : 'staff',
        loadChildren : () => import('src/app/views/staff/staff.module').then(m => m.StaffModule)
      },
      {
        path : 'workspace',
        loadChildren : () => import('src/app/views/workspace/workspace.module').then(m => m.WorkspaceModule)
      }
    ]
  },

];

@NgModule({

  imports: [
    CommonModule,
    RouterModule.forChild(routes)
  ],
  exports : [
    RouterModule
  ]
})
export class LayoutRoutingModule { }

标签: javascriptangulartypescriptangular-router

解决方案


推荐阅读