欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

宁皓 Angular:守卫 有大用

   这个课程主要训练的是使用 Angular 的 Guard,中文可以翻译成守卫。应用里的有些地方可能需要用户登录之后或者有特定的权限才能访问。我们可以去创建一些守卫,看守这些特别的地方,就是在用户访问他们的时候,会执行一些代码,判断一些条件,然后再决定是否可以让用户继续访问。

封面摄影:Simon W Xu

来自  https://ninghao.net/course/7704#info


# git branch                            #查看分支

# git commit -am "routing end"            #到暂存区,并提交

# git push ogigin routing                           #推送

# git log                           #查看日志

# git checkout master        #切换到master分支

# git merge routing            #合并routing分支到当前分支master

# git push origin master        #推送到origin远程的 master分支

# git checkout -b guard            #创建分支guard并切换到guard分支

# git push origin guard            #推送到origin远程的 guard  分支



# ng generate component modules/demo/login            #创建一个组件login

CREATE src/app/modules/demo/login/login.component.html (20 bytes)

CREATE src/app/modules/demo/login/login.component.spec.ts (592 bytes)

CREATE src/app/modules/demo/login/login.component.ts (271 bytes)

CREATE src/app/modules/demo/login/login.component.css (0 bytes)

UPDATE src/app/modules/demo/demo.module.ts (545 bytes)



# ng generate service modules/demo/auth/auth            #生成auth服务

CREATE src/app/modules/demo/auth/auth.service.spec.ts (347 bytes)

CREATE src/app/modules/demo/auth/auth.service.ts (133 bytes)



#    ng generate component modules/demo/admin           #生成组件admin

CREATE src/app/modules/demo/admin/admin.component.html (20 bytes)

CREATE src/app/modules/demo/admin/admin.component.spec.ts (592 bytes)

CREATE src/app/modules/demo/admin/admin.component.ts (271 bytes)

CREATE src/app/modules/demo/admin/admin.component.css (0 bytes)

UPDATE src/app/modules/demo/demo.module.ts (624 bytes)



# ng generate guard modules/demo/auth/auth            #生成一个守卫

? Which interfaces would you like to implement? CanActivate        #选择实现了CanActivate接口

CREATE src/app/modules/demo/auth/auth.guard.spec.ts (331 bytes)

CREATE src/app/modules/demo/auth/auth.guard.ts (457 bytes)




# ng generate component modules/demo/admin/admin-dashboard        #生成一个组件

CREATE src/app/modules/demo/admin/admin-dashboard/admin-dashboard.component.html (30 bytes)

CREATE src/app/modules/demo/admin/admin-dashboard/admin-dashboard.component.spec.ts (656 bytes)

CREATE src/app/modules/demo/admin/admin-dashboard/admin-dashboard.component.ts (310 bytes)

CREATE src/app/modules/demo/admin/admin-dashboard/admin-dashboard.component.css (0 bytes)

UPDATE src/app/modules/demo/demo.module.ts (747 bytes)



# ng generate guard modules/demo/admin/can-deactive    #生成一个实现CanDeactivate的守卫

? Which interfaces would you like to implement? CanDeactivate

CREATE src/app/modules/demo/admin/can-deactive.guard.spec.ts (367 bytes)

CREATE src/app/modules/demo/admin/can-deactive.guard.ts (554 bytes)



#ng generate service modules/post/services/post-detail-resolve            #生成一个叫post-detail-resolve的服务

CREATE src/app/modules/post/services/post-detail-resolve.service.spec.ts (414 bytes)

CREATE src/app/modules/post/services/post-detail-resolve.service.ts (146 bytes)




介绍与准备

1)介绍(Guard)

这个课程主要训练的是使用 Angular 的 Guard,中文可以翻译成守卫。应用里的有些地方可能需要用户登录之后或者有特定的权限才能访问。我们可以去创建一些守卫,看守这些特别的地方,就是在用户访问他们的时候,会执行一些代码,判断一些条件,然后再决定是否可以让用户继续访问。

守卫还可以阻止用户离开当前访问的地址,比如用户在当前页面上如果有未保存的内容,这时候他要离开去访问其它的地方的时候,守卫可以阻止用户离开,可以提示用户保存没保存的内容。

在打开一个组件之前,我们可以使用一些 Resolver 提前去把即将要打开的组件里面需要的一些数据准备好。

来自  https://ninghao.net/video/7706#info


2)准备项目(Guard)


查看一下项目当前的分支,显示是在 routing 分支上,

# git branch

看一下在这个分支上做的提交,

# git log 

最后一次提交是这个 Clearing secondary routes 。

把项目当前分支切换到 master ,

# git checkout master

然后在这个分支上去做一次合并,要合并的是 routing,

# git merge routing 

合并之后再检查一下在 master 分支上做的提交。

# git log

下面基于最后一次提交创建一个新的分支并且切换到这个新的分支上,分支的名字是 guard。

# git checkout -b guard 

推送一下 routing 分支,推送到 origin ,分支是 routing。

# git push origin routing 

再推送一下 master 分支,也把它推送到 origin。

# git push origin master 

最后再推送一下 guard 分支。

# git push origin guard

在这个课程里我对项目的修改都会保存在这个 guard 分支上,到时候你可以找到这个项目的远程,

# git remote -v

检查在 guard 分支上做的提交。

来自  https://ninghao.net/video/7707#info


3)创建 Login 组件与 Auth 服务


再创建一个组件,ng generate 生成一个 component,放在 modules/demo 里面,名字是 login。

# ng g c modules/demo/login

回到项目,打开刚才创建的这个组件的模板文件。里面先用一组标题元素,文字是 Login,再添加一个段落,Simulate login process. 最后再添加一个 button,文字是 Login。

打开 DemoRoutingComponent,在 Demo 模块的路由模块里添加一条新的路由,作为 demo 路由的子路由,路由的 path 是 login,对应的 component 是 LoginComponent。

再打开 Demo 组件的视图文件,在视图的 sidebar 里面,再添加一个链接,链接的文字是 Login,地址是 ./login。

预览

回到浏览器预览一下,打开 demo,再打开边栏上的这个 Login,右边显示的就是 LoginComponent 组件。

AuthService

下面可以再去创建一个用来作身份验证的服务,ng gengerate ,生成一个 service ,放在 modules/demo/auth 里面,名字是 auth 。

# ng g s modules/demo/auth/auth         ( ng generate service modules/demo/auth/auth )

再回到项目,打开刚才生成的 AuthService,在这个服务里可以先模拟一下身份验证的功能,先添加一个属性,名字是 isLoggedIn ,默认让它等于 false,用这个属性来表示用户的登录状态。

然后再添加两个方法,先添加一个 login ,这个方法做的事情就是把 isLoggedIn 属性的值设置成 true ,也就是只是使用了这个服务里的这个 login 方法,我们假设用户就已经登录了。在控制台上输出点文字,输出 Logged in !

再添加一个 logout 方法,这个方法里面,可以把 this.isLoggedIn 的值设置成 false 。使用这个方法也在控制台上输出点文字,输出 Logged out !

使用服务

打开 LoginComponent 组件,在这个组件里用一下刚才创建的 AuthService,在组件的 constructor 里面,添加一个 public authService,类型是 AuthService。

然后在组件里再添加一个 login 方法,方法里面用一下 this.authService.login() ,再添加一个 logout 方法,在这个方法里用一下 this.authService.logout()。

下面再修改一下这个组件的模板,在这个 Login 按钮的上面,绑定一个 click 事件,使用组件里的 login() 方法来处理,可以再用一个 *ngIf 指令,条件是 !authService.isLoggedIn,如果用户没登录,就显示这个 Login 按钮。

复制一份这个按钮,按钮文字换成 Logout,点击这个按钮,执行的是 logout(),*ngIf 判断的条件是检查 authService 里的 isLoggedIn。如果用户已经登录了,就在 LoginComponent 里面显示这个 Logout 按钮。

预览

回到浏览器可以预览一下,打开 Demo,再打开边栏上的 Login,右边显示的这个 LoginComponent 里面,有一个 Login 按钮,按一下这个按钮,会使用 AuthService 上的 login 方法。

用户登录以后,Logout 按钮会出现,控制台上输出了一个 Logged in,再按一下 Logout,用户登出以后,会显示 Login 按钮,控制台上会输出一个 Logged out !

来自   https://ninghao.net/video/7708#info

4)创建 Admin 组件


先在终端给项目创建一个组件,ng generate ,生成一个 component ,放在 modules/demo 里面,名字是 admin 。

# ng g c modules/demo/admin

回到项目,找到刚才生成的 Admin 组件的模板文件,一组标题,文字是 Admin,下面再添加一个段落文字,Here is admin area.

打开 Demo 模块的路由模块,在它里面需要再添加一条路由,可以放在 demo 路由的 children 里面,复制一份,修改一下路由的 path,换成 admin,再修改一下路由对应的组件,用一下 AmdinComponent 这个组件,注意要在文件顶部导入这个组件。

再打开 DemoComponent 组件的模板文件,在 sidebar 里面,添加一个链接,可以直接复制一份,修改一下链接文字,Admin ,链接的地址是 ./admin 。

预览

回到浏览器,打开 Demo,再打开边栏上的 Admin 链接,现在右边显示的就是 AdminCompoennt 组件的视图。

来自  https://ninghao.net/video/7709#info


守卫

5)守卫(Guard):canActivate


用户在访问路由的时候,你可能希望用户是登录的状态,并且有特定的权限,或得在显示路由组件的时候提前获取到一些数据,离开组件之前保存修改等等。这些情况我们都可以在路由上使用 Guard 来实现。

先去创建一个 Guard,在终端,执行一下 ng generate 生成一个 guard,放在 modules/demo/auth 的下面,这个守卫的名字可以叫 auth 。

# ng g g modules/demo/auth/auth  (  ng generate guard modules/demo/auth/auth )

提示  (为什么我这边没有提示) 让我们选择要生成的 Guard 要实施的接口,先用一下这个 CanActivate ,按一下空格选中它。

回到项目,找到刚才生成的 AuthGuard,在 app,modules,demo,auth 这个目录的下面。

守卫是个类,这个类实施了 CanActivate 接口,所以在这个类里面要添加一个 canActivate 方法。

这个方法现在 return 的是 true,这样就可以正常打开路由,如果它返回 false,就不能打开使用了这个 Guard 的路由。

暂时先让它 return 一个 false 。

然后在这个方法里,可以在控制台上输出点文字,输出一个 Auth guard。

应用 Guard

下面找个路由用一下 AuthGuard,打开 DemoRoutingModule,在这个路由模块里定义的 admin 这个路由的上面,用一下刚才我们创建的 Guard,在这条路由里添加一个 canActivate,它的值是个数组,里面添加一个 AuthGuard 。

预览

回到浏览器可以预览一下,点击 Demo,打开浏览器的控制台,按一下边栏上的 Admin,这次右边并没有显示 Admin 组件的视图。

因为在这个路由上用了一下 AuthGuard 守卫,现在守卫里的方法一直会 return false,所以无法打开这个 admin 。

你会发现在控制台上会输出一个 Auth guard,这个是因为我们在 admin 这条路由的上面用了一个 AuthGuard,在它的 canActivate 方法里,在控制台上输出了这个 Auth guard 文字。这就表示,访问当前这个 demo/admin 地址,就会应用 AuthGuard 这个守卫。

回到项目,修改一下 AuthGarud 守卫里的 canActivate 方法返回的值,换成 true。

再到浏览器上试一下,点击打开 Admin,这次就打开了,因为用在这个路由上的 AuthGuard 里的 canActivate 方法会返回 true。

来自   https://ninghao.net/video/7711#info


6)在守卫里使用服务


打开 AuthGuard ,在这个守卫里可以使用 AuthService 服务上提供的一些东西,先把它注入进来,在守卫类里添加一个 constructor,private authService,类型是 AuthService。

在守卫的 canActivate 方法里,可以检查一下用户的登录状态,判断一下,如果 this.authService.isLoggedIn 是 true,说明用户已经登录了,这种情况可以让这个方法 return true 。

不然可以把用户带到登录页面,让用户登录,这里需要用到 Router 提供的功能,可以把它也注入进来,在构造方法的参数里,添加一个 private router,类型是 Router。

然后在 canActivate 方法里,用一下 this.router.navigate,一个数组,里面添加一个 '/demo/login' 。

预览

下面到浏览器上试一下,先打开 Demo,然后点击 Admin ,路由用了 AuthGuard 守卫,在守卫的 canActivate 方法里,会检查用户的登录状态,如果没有登录,就会把用户带到这个 demo/login 页面。

按一下 Login 按钮,登录成功以后,再点击打开 Admin,这样就可以正常显示 AdminComponent 组件里的内容了。

来自   https://ninghao.net/video/7712#info


7)canActivateChild:守卫子路由


AuthGuard 守卫里实施了 CanActivate,我们把这个守卫用在了 admin 这个路由上,用它看守 admin 路由,只让登录的用户才能访问 admin 这个路由。如果 admin 里面包含了一些子路由,要守卫这些子路由可以使用 CanActivateChild 类型的守卫。

子路由

下面可以去定义两个子路由,打开 Demo 模块的路由模块,在这个 admin 路由里面,添加一个 children,里面添加需要的子路由。

可以先去创建一个组件,ng generate ,生成一个 component ,放在 modules/demo/admin 里面,名字是 admin-dashboard 。

#  ng g c modules/demo/admin/admin-dashboard

回到项目,继续定义 admin 的子路由,路由的 path 可以是 dashboard,路由的 component 是 AdminDashBoardComponent。

下面再定义一条路由,路由的 path 是 posts,路由的 component,用一下之前我们定义好的 Post 组件。

Admin 组件

打开 Admin 组件的模板文件,在这里要添加一个 router-outlet,用来输出路由的子路由。 在上面可以再添加两个子路由的链接,一组 a 标签,文字是 Dashboard,标签上用 routerLink 设置一下地址,./dashboard,再用 routerLinkActive 设置一下激活状态下的 css 类。

复制一份,修改一下链接文字,Posts ,地址是 ./posts。

预览

在浏览器上可以先试一下,打开 Demo,点击 Admin,提示要登录,按一下 Login,然后再回到 Admin ,控制台上会输出 Auth guard,这个文字是在 AuthGuard 里的 canActivate 方法里输出了。说明打开 Admin 路由的时候,调用了这个守卫里的 canActivate 方法。

再访问一下 Dashboard ,还有这个 Posts 链接 ,这两个路由是 admin 里的子路由,访问它们的时候并没有调用 AuthGuard 守卫里的 canActivate 方法。

canActivateChild

打开 AuthGuard,在这个守卫里,让它实施一下 CanActivateChild,这样在守卫类里需要添加一个 canActivateChild 方法。选中守卫类,按一下 command + . ,选择实施 CanActivateChild 接口,这样会在类里面添加需要的方法。

调一下这个方法的位置,把它放在 canActivate 方法的下面。

在这个方法里,你可以添加需要的代码判断用户是否可以访问子路由。暂时我们先在控制台上输出点文字,用 console.log ,输出 Auth guard canActivateChild. 下面再让方法 return true,方法如果最终 return 的是 false,就不能继续访问,如果 return 的是 true,就可以继续访问。

应用 canActivateChild

守卫子路由,可以使用 canActivateChild。先回到路由模块,可以在这个 admin 路由上,再添加一个 canActivateChild 属性,它的值是个数组,里面添加一个 AuthGuard 。这样就会使用这个 AuthGuard 守卫里的 canActivateChild 来守卫路由的子路由。

预览

回到浏览器再试一下,打开 Demo,点击 Admin,然后 Login, 打开 Admin ,再试着访问一下 Dashboard ,你会发现,控制台上输出了 Auth guard canActivateChild. 再打开 Posts 这个链接,控制台上又会输出一个 Auth guard canActivateChild。这就说明访问admin子路由的时候调用了Auth guard 这个守卫里面的 canActivateChild 这个方法

来自    https://ninghao.net/video/7713#info


8)自定义样式:Admin 组件


下面可以再添加点自定义的样式,主要设置一下 Admin 组件里的这个子导航的样式。回到项目,先打开 Admin 组件的模板文件,这里可以用一个 nav 标签,包装一下导航里的这两个链接。

再打开组件的样式表,先设置一下 nav 元素的样式,用 border-bottom,在底部添加一条边框,颜色是 #eee。用 margin-bottom 在底部添加点外边距,大小是 32px。

下面再设置一下 nav 元素里的 a 标签的样式,把 dispay 设置成 inline-block,再用 padding 添加点内边距,上下是 12px,左右是 16px。 底部的外边距,大小设置成 -1px。 文字的颜色是 rgba,颜色是黑色,不透明度可以是 0.7。

激活状态的 a 元素上面会有一个 active 类, nav a.active,激活状态下的文字的颜色是黑色,然后在底边可以添加一条黑色的边框。

演示视图的样式还有个地方需要修改一下,打开 demo.component.css ,找到里面的 .content,把它的 flex-grow 的值设置成 2。主要是为了让这个内容区域占满剩余的所有空间。

预览

回到浏览器预览一下,Login 之后,再打开 Admin, 然后切换显示一下 admin 里面的这两个子路由。

来自   https://ninghao.net/video/7714#info


9)canDeactivate:决定是否可以离开当前路由的守卫


用户离开页面,打开应用里的其它页面的时候,可能因为某些原因暂时不想让用户离开当前页面,比如可能正在编辑的内容还没有保存,用户如果离开这个页面,没保存的数据就会丢失。

在路由上使用 canDeactivate 类型的守卫,在用户离开当前路由打开应用里的其它路由的时候,可以检查一些条件,然后决定是否让用户离开。

canDeactivate

先去生成一个守卫,在终端项目的下面,用 ng 命令 generate 一个 guard,放在 modules,demo,admin 的下面,守卫的名字叫 can-deactivate。

# ng generate guard modules/demo/admin/can-deactive    ( ng g g modules/demo/admin/can-deactive )

执行一下,提示选择要实施的接口,(但是我这边没有看到提示)可以暂时不选择,直接回车。

回到项目,打开刚才生成的这个守卫,这个守卫的 implements 后面还没有设置要实施的东西,这个守卫要实施的是 CanDeactivate 接口,类型暂时先设置成 any,这个类型应该是组件的类型。

编辑器会在文件顶部自动导入 CanDeactivate。

实施这个接口,要在类里面添加一个特定的方法,可以选中这个类的名字,按一下 command + . 选择实施 CanDeactivate 接口,这样会在类里面添加一个 canDeactivate 方法。

方法接收一些参数。 冒号右边这些东西是这个方法可能会返回的值的类型。

这个守卫的 canDeactivate 方法如果最终 return 的值是 true,使用了这个守卫的路由就允许用户离开,去访问其它的地方,如果方法执行之后,最终 return 的是 false,就不允许用户离开当前路由。

在方法里,先在控制台上输出点文字,用一个 console.log,输出 Can deactivate guard. 然后让方法暂时先 return false 。

使用

下面找个地方用一下这个守卫,打开 Demo 模块的路由模块,在这个 admin 路由的上面,添加一个 canDeactivate 属性,它的值是个数组,里面可以添加要用在这条路由上的 canDeactivate 类型的守卫。也就是实施了 CanDeactivate 接口的守卫。

添加一个 CanDeactivateGuard,这个就是刚才我们创建的守卫。

预览

回到浏览器预览一下,登录一下,回到 Admin,然后试着离开这个页面,访问应用里的其它的地方。你会发现导航不管用了。

控制台上输出了一个 Can deactivate guard,因为在 Admin 这个路由上,用了一个 canDeactivate 类型的守卫,现在这个守卫里一直会 return false,所以不让用户离开当前这条路由。

按一下浏览器上的后退按钮,控制台上也会输出 Can deactivate guard 。 回到项目,打开 CanDeactivateGuard,这回让这个方法 return true 。

再回到浏览器试一下,按一下 Login,打开 Admin ,再试着访问一下其它的地方,这次就可以正常打开其它的地方了,因为用在 Admin 路由上的 CanDeactivateGuard 守卫的 canDeactivate 方法会一直返回 true。

来自   https://ninghao.net/video/7715#info


10)在 canDeactivate 守卫里执行组件里的方法


在使用 CanDeactivate 守卫的时候,判断是否允许用户离开当前路由,可能要根据路由对应的那个组件里的一些东西做判断。在这个守卫的 canDeactivate 方法里的这个 component 参数,它的值就是使用了这个守卫的路由对应的那个组件。

比如现在我们把这个守卫用在了 admin 这个路由上了,这个路由对应的组件是 AdminComponent。按住 alt 键,点击打开这个组件,在组件里添加一个方法,比如 canDeactivate ,方法里可以先在控制台上输出点文字。Admin component canDeactivate。

回到这个守卫,在这个方法里执行一下 compopnent 参数上的 canDeactivate 方法。

预览

再回到浏览器试一下,Login 之后,打开 Admin,然后试着离开这个路由。因为这个路由上用了 CanDeactivateGuard 守卫,守卫里的 canDeactivate 方法里执行了 component 参数上的 canDeactivate 方法。

这里这个 component 就是 admin 路由对应的 AdminComponent,也就是这个执行的组件上的 canDeactivate 方法就是来自这个 AdminComponent 组件。所以在控制台上会输出 Admin component canDeactivate。

confirm

回到项目,打开 AdminComponent 组件,它的这个 canDeactivate 方法,可以让它 return window.confirm,显示一个提示,信息是 Are you sure you want to leave?

用户如果按了确定,这个方法 return 的就是 true,如果按的是取消,方法 return 的就会是 false。

再打开守卫修改一下,可以让这个守卫 return 执行 component 上的 canDeactivate 方法的结果。

预览

回到浏览器可以试一下,打开 Admin 路由,然后再试着离开这个路由,这次会在页面上出现一个提示,按一下 Cancel 取消,会继续留在当前页面,再试一下,这次按一下对话框上的 OK,按钮,window.confirm 方法返回的值会是 true,所以这次就离开了当前的这个 Admin 路由。

来自   https://ninghao.net/video/7716#info


11)Resolve:提前准备好组件需要的数据

打开一个组件的时候,可以使用一些 Resolver 或者叫 Data Provider 提前准备好组件里面需要的一些数据。比如在一个内容列表,点击打开某个内容项目的详情的时候,内容详情组件里面需要请求后端服务获取到组件需要的数据,但是这个获取过程需要点时间,或者有可能获取的内容不存在,所以就没有必要打开这个内容详情页面。这种情况我们就可以使用 Resolver 提前去把组件需要的数据准备好。

先在浏览器上试一下,打开 Posts,会显示一组内容列表,再打开其它的一个内容项目,现在界面上会使用一个 PostDetailsComponent 组件。打开这个内容详情的时候,可以使用一个 Resolver 提前去把这个组件里需要的数据准备好。

回到项目,先打开 PostDetailsComponent 组件检查一下,现在这个组件里需要的数据是在组件的 ngOnInit 生命周期方法里准备好的。

在终端,给项目生成一个服务,ng generate 生成一个 service ,放在 modules/post/services 里面,名字叫 post-detail-resolve。

#  ng g s modules/post/services/post-detail-resolve  (ng generate service modules/post/services/post-detail-resolve)

然后找到刚才生成的这个服务,现在这个 PostDetailResolveService 是一个普通的类,把它变成一个 Resolver 或者叫 Data Provider,可以让这个类去实施一下 Resolve,implements 一下 Resolve。这个 Resolve 来自 @angular/router 。

Resolve 的数据类型可以设置成 Post,这个 Post 是之前我们自己定义的一个类。

这个服务类实施了 Resolve 接口以后,需要在类里面添加一个 resolve 方法,你可以选中这个类的名字,然后按一下 command + . 再选择实施 Resolve 接口。

或者也可以直接手工在类里面,添加一个 resolve 方法,这个方法 return 的值最终应该是一个 Post 类型的值。在方法里暂时先手工 return 一个 Post,这个 Post 数据里面需要一个 id 属性,值应该是一个数字,还需要一个 title 属性,值的类型是字符串。另外还可以包含一个 body 属性,不过这个属性是可选的,所以可以不需要设置 body 属性的值。

return 之前,先在控制台上输出点文字,输出 Post detail resolve service.

使用 Resolve

下面去用一下这个 Resolver,打开 Post 模块的路由模块,找到这个 path/:id 这条路由,这个路由的组件是 PostDetailsComponent,就是用来显示内容详情用的一个组件。

在这个路由上,添加一个 resolve ,它的值可以是个对象,属性的名字就是给 Resolver 返回的数据起的名字,比如可以叫它 entity,然后是对应的 Resolver,用一下刚才创建的 PostDetailResolveService。 这样在这个路由组件,也就是 PostDetailsComponent 组件里,就可以使用这个名字是 entity 的数据了,也就是 PostDetailResolveSerivce 里的 resolve 方法最终返回的那个数据。

预览

先回到浏览器试一下,打开内容列表,再打开一个内容项目,你会发现控制台上先输出了一个 Post detail resolve service,接着又输出了一个数字。

这个数字是地址里的这个参数的值,输出这个值是在 PostDetailsComponent 里面做的,这也就证明了,Angular 先执行了路由上的用的 Resolver,这里就是 PostDetailResolveService。然后才会给我们创建这个 PostDetailComponent 组件。

来自   https://ninghao.net/video/7717#info


12)使用 Resolve 准备内容详情组件需要的数据


回到项目,在这个 Resolver 里面,暂时我们手工 return 的一个内容数据,下面可以再修改一下,这个 Resolver 返回的值可以使用 PostService 服务获取到。在类里先把它作为依赖注入进来,在构造方法里,添加一个 private postService,类型是 PostService。

这个 resolve 方法里面可以添加一个 route 参数,类型是 ActivateRouteSnapShot。然后在方法里,添加一个 postId,它的值,用一下 route 参数上的 paramMap 上的 get ,得到地址里的 id 参数的值,使用 PostService 获取内容数据的时候需要用到这个 id 参数的值,在前面加上一个加号,可以把这个值转换成数字类型的。

方法 return 的东西可以用一下 this.postService.show 这个方法,把 postId 交给这个方法。PostService 服务里的这个 show 可以帮我们得到指定的文章内容。

组件

下面再打开 PostDetailsComponent 组件,在组件的 ngOnInit 方法里,注释掉之前我们添加的获取内容数据用的代码,因为这个组件的路由那里用的那个 PostDetailResolveService,已经帮我们把组件需要的数据准备好了。

这里可以用一下 this.route.data,它是一个 Observable,用一下 subscribe 订阅一下它的值,这个值就是 Resolver 返回的值。比如我们叫它 data,这个 data 里面已经有个 entity 属性,这个属性的值应该是个 Post。

因为在定义路由的时候,配置的 resolve 里面,给 PostDetailResolveService 返回的值起的名字就叫 entity 。

方法里面设置一下组件的 this.entity 的值,让它等于 data 里的 entity。

预览

回到浏览器,预览一下,先打开内容列表,然后再打开一个内容项目,界面上仍然会正常地显示文章内容。现在这个界面里的 PostDetailsComponent 组件需要的数据,是用的一个 Resolver 提前给它准备好的。

来自  https://ninghao.net/video/7718#info

普通分类: