Angular路由跳转是Angular应用程序中最重要的功能之一,它可以帮助开发人员在不同的页面之间进行跳转。Angular提供了一个内置的路由器,它可以帮助开发人员在不同的页面之间进行跳转。
Angular提供了一个内置的RouterModule,它可以帮助开发人员在不同的页面之间进行跳转。RouterModule提供了一个Routes数组,其中包含所有要使用的URL和对应的组件。当用户请求特定URL时,RouterModule会将其映射到对应的组件上。
const routes: Routes = [ { path: '', component: HomeComponent }, { path: 'about', component: AboutComponent }, { path: 'contact', component: ContactComponent } ];
此外,RouterModule还提供了一个NavigationExtras对象,它可以帮助开发人员在不同页面之间传递数据。NavigationExtras对象允许开发人员将数据作为queryParams或fragment传递到目标组件中。
this.router.navigate(['/about'], { queryParams: { id: 123 } });
此外,RouterModule还提供了一个CanActivateGuard来保护特定URL不能随意使用。CanActivateGuard是一个函数,它会在用户尝试使用特定URL时检查是否有权使用该URL。如果CanActivateGuard函数返回false,则表明该URL不能使用;如果CanActivateGuard函数返回true,则表明该URL可以使用。
@Injectable() export class AuthGuard implements CanActivate { canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean { return this.authService.isAuthenticated(); } }
总而言之,Angular RouterModule是Angular应用程序中最重要的功能之一,它可以帮助开发人员在不同的页面之间进行快速、有效、安全的跳转。RouterModule包含了所有必要的工具和API来帮助开发人员快速、有效、安全地在不同页面之间进行跳转。
对下列概念有基本的理解:
路由能让用户在应用中的不同路由之间导航。当用户从一个路由导航到另一个路由时,Angular 路由器会把这个 URL 映射到一个相关的组件,并显示其视图。为这种路由转换添加动画,将极大地提升用户体验。
Angular 路由器天生带有高级动画功能,它可以让你为在路由变化时为视图之间设置转场动画。要想在路由切换时生成动画序列,你需要首先定义出嵌套的动画序列。从宿主视图的顶层组件开始,在这些内嵌视图的宿主组件中嵌套添加其它动画。
要启用路由转场动画,需要做如下步骤:
让我们以两个路由之间的导航过程来解释一下路由转场动画,Home 和 About 分别与 HomeComponent
和 AboutComponent
的视图相关联。所有这些组件视图都是顶层视图的子节点,其宿主是 AppComponent
。我们将实现路由器过渡动画,该动画会在出现新视图时向右滑动,并当用户在两个路由之间导航时把旧视图滑出。
首先,使用 RouterModule
类提供的方法来配置一组路由。该路由配置会告诉路由器该如何导航。
使用 RouterModule.forRoot
方法来定义一组路由。同时,把其返回值添加到主模块 AppModule
的 imports
数组中。
注意:
在根模块 AppModule
中使用 RouterModule.forRoot
方法来注册一些顶层应用路由和提供者。对于特性模块,则改用 RouterModule.forChild
方法。
下列配置定义了应用程序中可能的路由。
import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { RouterModule } from "@angular/router";
import { AppComponent } from "./app.component";
import { OpenCloseComponent } from "./open-close.component";
import { OpenClosePageComponent } from "./open-close-page.component";
import { OpenCloseChildComponent } from "./open-close.component.4";
import { ToggleAnimationsPageComponent } from "./toggle-animations-page.component";
import { StatusSliderComponent } from "./status-slider.component";
import { StatusSliderPageComponent } from "./status-slider-page.component";
import { HeroListPageComponent } from "./hero-list-page.component";
import { HeroListGroupPageComponent } from "./hero-list-group-page.component";
import { HeroListGroupsComponent } from "./hero-list-groups.component";
import { HeroListEnterLeavePageComponent } from "./hero-list-enter-leave-page.component";
import { HeroListEnterLeaveComponent } from "./hero-list-enter-leave.component";
import { HeroListAutoCalcPageComponent } from "./hero-list-auto-page.component";
import { HeroListAutoComponent } from "./hero-list-auto.component";
import { HomeComponent } from "./home.component";
import { AboutComponent } from "./about.component";
import { InsertRemoveComponent } from "./insert-remove.component";
import { QueryingComponent } from "./querying.component";
@NgModule({
imports: [
BrowserModule,
BrowserAnimationsModule,
RouterModule.forRoot([
{ path: "", pathMatch: "full", redirectTo: "/enter-leave" },
{
path: "open-close",
component: OpenClosePageComponent,
data: { animation: "openClosePage" }
},
{
path: "status",
component: StatusSliderPageComponent,
data: { animation: "statusPage" }
},
{
path: "toggle",
component: ToggleAnimationsPageComponent,
data: { animation: "togglePage" }
},
{
path: "heroes",
component: HeroListPageComponent,
data: { animation: "filterPage" }
},
{
path: "hero-groups",
component: HeroListGroupPageComponent,
data: { animation: "heroGroupPage" }
},
{
path: "enter-leave",
component: HeroListEnterLeavePageComponent,
data: { animation: "enterLeavePage" }
},
{
path: "auto",
component: HeroListAutoCalcPageComponent,
data: { animation: "autoPage" }
},
{
path: "insert-remove",
component: InsertRemoveComponent,
data: { animation: "insertRemovePage" }
},
{
path: "querying",
component: QueryingComponent,
data: { animation: "queryingPage" }
},
{
path: "home",
component: HomeComponent,
data: { animation: "HomePage" }
},
{
path: "about",
component: AboutComponent,
data: { animation: "AboutPage" }
},
])
],
home
和 about
路径分别关联着 HomeComponent
和 AboutComponent
视图。该路由配置告诉 Angular 路由器当导航匹配了相应的路径时,就实例化 HomeComponent
和 AboutComponent
视图。
除了 path
、component
之外,每个路由定义中的 data
属性也定义了与此路由有关的动画配置。当路由变化时,data
属性的值就会传给 AppComponent
。你还可以在路由配置中传递其它的值供路由的动画使用。data
属性的值必须满足 routeAnimation
中定义的转场动画的要求,稍后我们就会定义它。
注意:
这个 data
中的属性名可以是任意的。比如,上面例子中使用的名字 animation 就是随便起的。
配置好路由之后,还要告诉 Angular 路由器当路由匹配时,要把视图渲染到那里。你可以通过在根组件 AppComponent
的模板中插入一个 <router-outlet>
容器来指定路由出口的位置。
ChildrenOutletContexts
包含有关插座和激活路由的信息。我们可以用每个 Route
的 data
属性来为我们的路由转换设置动画。
<div [@routeAnimations]="getRouteAnimationData()">
<router-outlet></router-outlet>
</div>
AppComponent
中定义了一个可以检测视图何时发生变化的方法,该方法会基于路由配置的 data
属性值,将动画状态值赋值给动画触发器(@routeAnimation
)。下面就是一个 AppComponent
中的范例方法,用于检测路由在何时发生了变化。
constructor(private contexts: ChildrenOutletContexts) {}
getRouteAnimationData() {
return this.contexts.getContext("primary")?.route?.snapshot?.data?.["animation"];
}
这里的 getRouteAnimationData()
方法会获取这个 outlet 指令的值(通过 #outlet="outlet"
),并根据当前活动路由的自定义数据返回一个表示动画状态的字符串值。可以用这个数据来控制各个路由之间该执行哪个转场。
动画可以直接在组件中定义。对于此范例,我们会在独立的文件中定义动画,这让我们可以复用这些动画。
下面的代码片段定义了一个名叫 slideInAnimation
的可复用动画。
export const slideInAnimation =
trigger("routeAnimations", [
transition("HomePage <=> AboutPage", [
style({ position: "relative" }),
query(":enter, :leave", [
style({
position: "absolute",
top: 0,
left: 0,
width: "100%"
})
]),
query(":enter", [
style({ left: "-100%" })
]),
query(":leave", animateChild()),
group([
query(":leave", [
animate("300ms ease-out", style({ left: "100%" }))
]),
query(":enter", [
animate("300ms ease-out", style({ left: "0%" }))
]),
]),
]),
transition("* <=> *", [
style({ position: "relative" }),
query(":enter, :leave", [
style({
position: "absolute",
top: 0,
left: 0,
width: "100%"
})
]),
query(":enter", [
style({ left: "-100%" })
]),
query(":leave", animateChild()),
group([
query(":leave", [
animate("200ms ease-out", style({ left: "100%", opacity: 0 }))
]),
query(":enter", [
animate("300ms ease-out", style({ left: "0%" }))
]),
query("@*", animateChild())
]),
])
]);
该动画定义做了如下事情:
query()
来确定哪个子视图正在进入或离开宿主视图路由的变化会激活这个动画触发器,并应用一个与该状态变更相匹配的转场
注意:
这些转场状态必须和路由配置中定义的 data
属性的值相一致。
通过将可复用动画 slideInAnimation
添加到 AppComponent
的 animations
元数据中,可以让此动画定义能用在你的应用中。
@Component({
selector: "app-root",
templateUrl: "app.component.html",
styleUrls: ["app.component.css"],
animations: [
slideInAnimation
]
})
那么,我们来分解一下这个动画定义,并仔细看看它做了什么……
在转场期间,新视图将直接插入在旧视图后面,并且这两个元素会同时出现在屏幕上。要防止这种行为,就要修改宿主视图,改用相对定位。然后,把已移除或已插入的子视图改用绝对定位。在这些视图中添加样式,就可以让容器就地播放动画,并防止某个视图影响页面中其它视图的位置。
trigger("routeAnimations", [
transition("HomePage <=> AboutPage", [
style({ position: "relative" }),
query(":enter, :leave", [
style({
position: "absolute",
top: 0,
left: 0,
width: "100%"
})
]),
使用 query()
方法可以找出当前宿主组件中的动画元素。query(":enter")
语句会返回已插入的视图,query(":leave")
语句会返回已移除的视图。
假设你正在从 Home 转场到 About,Home => About
。
query(":enter", [
style({ left: "-100%" })
]),
query(":leave", animateChild()),
group([
query(":leave", [
animate("300ms ease-out", style({ left: "100%" }))
]),
query(":enter", [
animate("300ms ease-out", style({ left: "0%" }))
]),
]),
]),
transition("* <=> *", [
style({ position: "relative" }),
query(":enter, :leave", [
style({
position: "absolute",
top: 0,
left: 0,
width: "100%"
})
]),
query(":enter", [
style({ left: "-100%" })
]),
query(":leave", animateChild()),
group([
query(":leave", [
animate("200ms ease-out", style({ left: "100%", opacity: 0 }))
]),
query(":enter", [
animate("300ms ease-out", style({ left: "0%" }))
]),
query("@*", animateChild())
]),
])
在设置了视图的样式之后,动画代码会执行如下操作:
query(":enter style({ left: "-100%"})
会匹配添加的视图,并通过将其定位在最左侧来隐藏这个新视图。animateChild()
,来运行其子动画。group()
函数使内部动画并行运行。group()
函数中:此动画将导致 about
视图从左侧划入。
animateChild()
方法,以运行其子动画。
你现在有了一个基本的路由动画,可以在从一个视图路由到另一个视图时播放动画。
持续更新你的Angular项目就像Web及其整个生态系统一样,Angular也在持续改进中。Angular平衡了持续改进与强调稳定性之间的冲突,...
AngularJS ng-init 指令 AngularJS 参考手册AngularJS 实例初始化应用时创建一个变量:div ng-app="" ng-init="myText='Hello...
AngularJS ng-readonly 指令 AngularJS 参考手册AngularJS 实例设置输入框为只读:Readonly: input type="checkbox" ng-model="al...
本节为你介绍Node.jsQueryStrings。稳定性: 3 - 稳定该Node.js模块提供了一些处理query strings的工具,你可以通过以下方式访问...
TypeScript 算术运算符示例假设变量a和b中的值分别为10和5。运算符描述示例+(加法)返回操作数的总和a + b = 15-(减法)返回值...
TypeScript Number方法 toFixed()toFixed()方法格式化一个小数点右侧具有特定位数的数字。语法number.toFixed( [digits] )参数详...
决策结构要求程序员指定由程序进行评估或测试的一个或多个条件,以及在条件被确定为true时要执行的一个或多个语句,以及如果条件...
JavaScript 全局JavaScript 全局属性和方法可用于创建Javascript对象。JavaScript 全局属性属性描述Infinity代表正的无穷大的数...
HTML DOM Blockquote 对象Blockquote 对象Blockquote 对象代表着一个 HTML 引用(blockquote)块元素。 blockquote 标签定义摘自另...