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 文档了解更多信息。
您可以浏览下面提到的博客以进行部署。
这里主要要注意的是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>
我正在使用 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 文档了解更多信息。
您可以浏览下面提到的博客以进行部署。
这里主要要注意的是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>