Angular 如果 URL 是手动写入的,请刷新应用程序

Angular refresh the application if the URL is written manually

我正在使用 Angular 6,但我遇到了路线更改方面的问题。 如果我使用 routerLink 或 navigate() 方法在应用程序中导航,它会正常工作,因为它只加载新模块(如果需要)。 但是例如,如果我在这个 link: localhost:8080/home 中,我单击 URL,取消 'home',写入 'profile' 并按 Enter,它正确地进入了个人资料页面,但重新加载了应用程序(也是应用程序组件)。为什么?我想不通。 这是我的路线:

const appRoutes: Routes = [
  { path: 'home', component: HomeComponent, canActivate: [AuthGuard] },
  { path: 'profile', component: ProfileComponent, canActivate: [AuthGuard] },
  { path: 'login', component: LoginComponent },
  { path: '', redirectTo: 'home', pathMatch: 'full' },
  { path: '**', component: PageNotFoundComponent }
];

@NgModule({
  imports: [
    RouterModule.forRoot(appRoutes, { preloadingStrategy: PreloadAllModules })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule { }

也许问题出在 auth-guard 上?

@Injectable()
export class AuthGuard implements CanActivate {

constructor(private store: Store<fromApp.AppState>, private route: ActivatedRoute, private router: Router) {
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    return this.store.select('auth')
        .pipe(take(1),
            map((authState: fromAuth.State) => {
                if (authState.authenticated) {
                    return true;
                } else {
                    let sessionStorageToken: string = sessionStorage.getItem('token');
                    if (sessionStorageToken) {
                        this.store.dispatch(new AuthActions.Login());
                        this.store.dispatch(new AuthActions.SetToken(sessionStorageToken));
                        return true;
                    } else {
                        let url = state.url;
                        this.router.navigate(['/login', { redirectTo: url }]);
                        return false;
                    }
                }
            }));
}
}

这是profile.module.ts:

@NgModule({
declarations: [
    ProfileComponent
],
imports: [
    CommonModule,
    FormsModule
]
 })
 export class ProfileModule { }

当您在 Angular 中浏览 routerLink 时,底层 JavaScript 正在确定向浏览器提供的内容。这意味着当 URL 地址通过 Angular 路由器更改时,它会获取更改并相应地为组件提供服务。

当您手动更新 URL 并按回车键时,就像转到一个新网页一样。这意味着服务器将需要重新提供基础网站 http://localhost:1234,然后应用程序将在那里处理路由 /profile 并提供所需的组件。

我试图以一种非常简单的方式对其进行解释,如需更详尽的解释,请查看 Angular docs

路由基本上用于延迟加载应用程序,一次加载一个模块。 每条路线都依赖于前一条路线,依此类推。 所以当你手动输入一个url时,应用程序会重新加载路由中的所有组件。

使用routerLink时,JavaScript改变了URL,即不认为是重新加载网页

但是,当您在地址栏中按下回车键时,页面会重新加载,即内容会再次从为 index.html 提供服务的服务器提供(如果您没有任何其他 HTML 定义为代替索引提供),因此应用程序重新初始化。

这就是重新加载所有组件的原因。

根据@Wesley 的建议,您可以参考 angular 文档了解更多信息。

https://angular.io/guide/router

您可以浏览下面提到的博客以进行部署。

https://arjunphp.com/deploy-angular-app-production-nginx/

这里主要要注意的是try_files $uri $uri/ /index.html =404;。当在地址栏上输入时,NGINX 首先检查给定的 URL 是否映射到服务器上的某个文件/路由。如果它不存在,在我们的例子中 localhost:8080/profile,则不存在,因为没有这样的物理路径。因此,NGINX 将为 /index.html 文件提供服务,该文件又会获取所有 JS 文件,这些文件又会处理路由。

如果你需要使用API,你可以使用NGINX的反向代理机制重定向,例如/api/路径到你对应的服务器。

你可以使用

RouterModule.forRoot(
  ROUTES,
  { useHash: true }
)],

哈希将阻止应用程序重新加载。 因此,当您在地址栏上按下回车键时,应用程序只会更改要显示的组件。

我来晚了回答这个问题,但也许这也会对某人有所帮助。

您可以创建一个 .htaccess 文件,将所有请求传输到您的 index.html 文件

.htaccess

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.html [L]
</IfModule>