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

这里的技术是共享的

You are here

宁皓网 Angular:路由 有大用

   使用 Angular 的路由功能。

   封面摄影:Margarita Calderó

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


# git branch          #查看当前分支 

        当前分支为 forms

# git master         #切换到master分支

# git merge forms        #合并forms分支到当前分支(master)

# git checkout -b routing    #创建routing分支,并切换到它

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

# git push origin master    #推送到远程origin的master分支上(不必在当前的分支推送)

# git push origin forms     #推送到远程origin的forms分支上(不必在当前的分支推送)

# git remote -v                #查看远程的名称,显示更详细的信息 ( v  verbose )            # 显示的结果中有 fetch 用来提取,push 用来推送


# ng generate component core/components/header  #生成组件,路径在  src/app/core/components/header/ 下面

CREATE src/app/core/components/header/header.component.html (21 bytes)       #组件的模板文件

CREATE src/app/core/components/header/header.component.spec.ts (599 bytes)

CREATE src/app/core/components/header/header.component.ts (275 bytes)

CREATE src/app/core/components/header/header.component.css (0 bytes)

UPDATE src/app/app.module.ts (716 bytes)        #组件自动更新最适合于它的模块文件



ng generate component core/components/page-not-found            #生成一个组件

CREATE src/app/core/components/page-not-found/page-not-found.component.html (29 bytes)        #组件的模板文件

CREATE src/app/core/components/page-not-found/page-not-found.component.spec.ts (643 bytes)

CREATE src/app/core/components/page-not-found/page-not-found.component.ts (305 bytes)

CREATE src/app/core/components/page-not-found/page-not-found.component.css (0 bytes)

UPDATE src/app/app.module.ts (843 bytes)              #组件自动更新最适合于它的模块文件



# ng generate module modules/post/post-routing --module post              #生成一个模块,指定生成的模块放在post 模块下面

CREATE src/app/modules/post/post-routing/post-routing.module.ts (197 bytes)

UPDATE src/app/modules/post/post.module.ts (721 bytes)            #更新了post模块


# ng generate module modules/post/post-routing --module post --flat             #生成一个模块,指定生成的模块放在post 模块下面(--module post),--flat是平滑的意思,就是说 post-routing 不会在一个单独的post-routing目录里面  直接会放在 modules/post/ 这个目录里面。

CREATE src/app/modules/post/post-routing.module.ts (197 bytes)


# ng generate module modules/user/user-routing --module user --flat             #生成一个模块,指定生成的模块放在user 模块下面(--module user),--flat是平滑的意思,就是说 user-routing 不会在一个单独的user-routing目录里面  直接会放在 modules/user/ 这个目录里面。

CREATE src/app/modules/user/user-routing.module.ts (197 bytes)

UPDATE src/app/modules/user/user.module.ts (461 bytes)



# ng generate module modules/demo --routing --module app        #生成一个模块,--routing 表示带有单独的route模块 , --module app 表示生成的这个模块在app模块下面

CREATE src/app/modules/demo/demo-routing.module.ts (247 bytes)

CREATE src/app/modules/demo/demo.module.ts (272 bytes)

UPDATE src/app/app.module.ts (870 bytes)



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

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

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

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

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

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


# ng generate component modules/demo/child-routes                #生成组件 child-routes 

CREATE src/app/modules/demo/child-routes/child-routes.component.html (27 bytes)

CREATE src/app/modules/demo/child-routes/child-routes.component.spec.ts (635 bytes)

CREATE src/app/modules/demo/child-routes/child-routes.component.ts (298 bytes)

CREATE src/app/modules/demo/child-routes/child-routes.component.css (0 bytes)

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



# ng generate component core/components/message-box        #生成组件 

CREATE src/app/core/components/message-box/message-box.component.html (26 bytes)

CREATE src/app/core/components/message-box/message-box.component.spec.ts (628 bytes)

CREATE src/app/core/components/message-box/message-box.component.ts (294 bytes)

CREATE src/app/core/components/message-box/message-box.component.css (0 bytes)

UPDATE src/app/app.module.ts (1014 bytes)


介绍与准备

1)介绍(Routing)

先去添加点自定义的样式,设置一下内容列表的样式,还有用户注册表单的样式。单独创建一个 Header 组件,把应用的头部视图放在这个组件里。

然后再去了解一下 Angular 应用里的路由功能,定义各种不同类型的路由,比如重定向路由通配符路由等等。应用的路由可以使用一些自定义的路由模块管理,我们会去创建两个路由模块,分别管理内容还有用户的路由。

最后再了解一下路由链接,路由的活动状态,还有定义与使用子路由与二级路由。

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

2)准备项目

先检查一下项目当前的分支,显示是在 forms 这个分支上,

# git branch

看一下我在这个分支上做的提交,最后一次提交是 FormBuilder。

# git log 

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

# git checkout master

在这个分支上做一次合并,要合并的是 forms 分支。

# git merge forms

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

# git log

显示最后一次是 FormBuilder。

下面去做这个课程创建一个分支并且切换到这个分支上,git checkout -b 分支的名字是 routing 。

# git checkout -b routing

把新创建的分支推送到 origin 远程。

# git push origin routing

可以再推送一下 master 分支,

# git push origin master

推送到 origin,分支是 master。

最后可以再推送一下 forms 分支,

# git push origin forms

推送到 origin,分支是 forms。

在这个课程里对项目的修改都会保存在 routing 分支上,

# git remote -v

到时候你可以浏览这个项目的远程仓库,找到 routing 分支,看一下我在这个分支上对项目做的一些提交。

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

3)内容列表的自定义样式


应用的全局样式可以放在 src 下面的 styles.css 这个样式表里,应用里的所有的组件都可以使用在这个样式表里添加的样式。先设置一下 body 元素的样式,用 font-family 设置一下字体。 sans-serif 。 再把元素的 padding 还有 margin 属性的值都设置成 0 。

下面再设计一下 a 元素的样式,用 text-decoration 去掉链接下划线。再用 color 设置一下链接文字的颜色。

PostComponent

在 modules,post 里面,打开 PostComponent 组件的视图,这里现在用了一组 ul 元素,可以把它换成一个 div 。元素上添加一个类,名字是 list。

然后再找到 PostItemComponent 组件的视图,把这里用的这个 li 元素,换成 div,元素上添加一个类,名字是 list__item 。

回到 styles.css 样式表,在这里设置一下 list__item 类的样式,用 border-bottom 在元素的下边添加一条实线边框,颜色是 #eee。 再用 padding-bottom 在下边添加点内边距。大小是 8px 。

在 PostComponent 视图里的标题元素上,添加一个 css 类,名字是 title 。回到样式表再设计一下这个类的样式,名字是 title,用 border-bottom 添加一条底边的边框,类型是实线,颜色是 #eee 。 接着再用 padding-bottom ,下边的内边距设置成 16px。

AppComponent

打开 AppComponent 组件的视图,在这个 router-outlet 的周围,可以用一组 div 包装一下,在这个包装上添加一个 container 类。

然后再去设置一下 container 类的样式,把它的四个边的内边距设置成 32px 。

来自  https://ninghao.net/video/7686


4)注册表单的自定义样式

打开应用的全局样式,styles.css,在这个样式表里设计一下页面显示的这个注册用户用的表单。样式的选择器可以使用属性选择器,input,type 属性的值是 text,逗号分隔一下,input,type 属性的值是 password。

先用 padding 添加点内边距,大小是 8px,width 设置成 100%,可以再用 max-width 设置一下最大的宽度,大小是 400px,元素的 box-sizing 可以设置成 border-box。 最后再用 border 设置一下元素的边框的样式,大小是 1px ,类型是 solid,颜色可以用 rgba 的颜色,0,0,0, 不透明度是 0.3 。

然后再设置一下 label 元素的样式,用 text-transform 设置成 uppercase ,文字变成大写的,用 letter-spacing 添加点字间距,大小是 2px。 再用 font-size 设置一下字号,大小是 12px ,然后用 font-weight ,值设置成 bold。

这个表单上还有一个按钮,元素是 button,有个 type 属性,类型是 submit。先去掉按钮元素上的边框,把 border 设置成 none ,background 背景颜色可以设置成黑色。下面再用 color,文字的颜色设置成白色。最后再用 padding 添加点内边距,上下是 10px,左右是 24px 。

再预览一下这个表单,表单元素上还有一点自定义的样式,这个样式是我们之前在组件的样式表里添加的。回到项目,打开这个组件的样式表。

剪切一下这块样式,把它放在应用的全局样式里。 最后再到浏览器上预览一下这个表单。


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

5)Header 组件与样式


应用顶部这块视图可以单独把它放在一个组件里,在这个组件里可以包含应用的标志,导航菜单等等。在终端,用命令生成一个组件,ng generate 生成一个 component ,放在 core/components 里面,名字叫 header。

回到项目,先打开应用里的 AppComponent 组件的模板文件,先剪切一下视图里的这个 h1 元素,换成一个 app-header 。

然后打开刚才我们用命令生成的 HeaderComponent 组件的模板文件,把 h1 元素放在这个视图里面。模板里绑定输出了一个 title 属性,这个属性之前是在 AppComponent 组件里了,剪切一下这个属性。把它放在 HeaderComponent 组件里。

还有一块样式, AppCompoennt 组件的样式表里,剪切一下,打开 HeaderComponent 组件的样式表,把样式放在这里。在组件样式表里的样式只对当前这个组件有效。

打开 HeaderComponent 组件的模板文件,在修改一下,先用一组 header 元素包装一下这个 h1 元素。然后在这个 header 里面,可以添加两个导航。

一组 nav 标签,里面添加一个 a 标签,文字是 Posts 。

在这个 header 里可以再添加一个导航,一组 nav .. 里面添加一组 a 标签,文字是 Register 。

样式

下面可以去设计一下这个组件的样式,打开组件的样式表,在这个 h1 元素的样式里,先用 font-size 设置一下字号,大小是 18px,再用 padding 添加点内边距,上下是 4px,左右是 16px 。

然后可以设置一下 header 的样式,display 设置成 flex ,然后用 border-bottom ,在元素的下边,添加一条实线的边框,颜色是 #eee。

再设置一下导航元素的样式,元素的名字是 nav,它的 align-self 设置成 center,再用 padding 添加点内边距,上下是 8px,左右是 16px。

导航元素里的 a 标签的样式也需要单独设置一下,display 设置成 inline-block,再用 padding 添加点内边距,上下是 4px,左右是 8px。文字的颜色可以使用 rgba 类型的颜色,颜色是黑色,不透明度是 0.7。

我打算让 header 里的第二个导航元素靠右显示,样式选择器可以这样写,nav:nth-child,2 ,把它的 flex-grow 设置成 2 。

完成以后可以到浏览器上再预览一下。

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

路由

6)路由(Routing)


要使用 Angular 的路由功能,你需要保证项目里的已经安装了 @angular/router 这个包,在创建 Angular 项目的时候我选择了要使用 Router 功能,所以项目里直接就会包含这个包。如果不包含就要单独去安装一下它

你可以直接在 AppModule 里配置使用路由,或者也可以单独创建一些 Routing 类型的模块。比如在我们这个项目里,有个 AppRoutingModule 模块。

在这个模块里之前我们已经定义了几条路由,路由一般都有一个 path,它是路由的地址,还有一个 component,就是打开这个地址要显示的组件。

定义路由的时候可以在地址里包含一些参数,这些参数可以使用冒号开头,比如这个 posts/:id,最后的这个 :id 就是这个地址里的参数,也就是它的值是动态的,这里表示的就是内容的 id 号。

在路由对应的组件里我们可以得到这个地址里的 id 参数的值,然后可以根据这个值动态的去获取到组件里需要的对应的那个内容数据。

在 AppComponent 的模板文件里,用了一个 router-outlet,路由对应的视图显示在 router-outlet 这里。

在路由模块里需要导入 RouterModule 模块,这个模块来自 @angular/router 这个包。

在这个 AppRoutingModule 模块里,用了 RouterModule 的 forRoot 方法配置了一下路由,把上面定义好的 routes 交给了这个方法。然后在模块的 exports 里导出了这个 RouterModule。

这样在 AppModule 里面导入了这个 AppRoutingModule 模块以后就可以使用路由功能了,应用里会包含我们在 AppRoutingModule 里定义的这些路由。

预览

再到浏览器上试一下,访问 posts ,会显示一个内容列表,点击打开列表里面的一个内容项目,会显示对应的内容。

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


7)定义重定向路由(redirectTo)


先访问一下应用的根,现在会显示一个空白,因为我们还没有定义这条路由。我打算在访问应用的根的时候,可以重定向到 posts 这个地址。

回到项目,打开 AppRoutingModule,在这个模块的 routes 里面,添加一条新的路由,路由的 path 是一个空白。然后用 redirectTo 设置一下要重定向到的位置,这里可以设置成 /posts。

接着再用 pathMatch 设置一下路径的匹配,它的值默认是 prefix,这里我们设置成 full。

预览

回到浏览器先试一下,直接在浏览器上访问应用的根。你会发现,现在会被重定向到 posts 这个地址。

routerLink

下面再去设置一下这个 Header 大标题的链接,回到项目,打开 HeaderComponent 组件的模板文件,找到它里面的这个 h1 元素,在它的周围添加一组 a 标签。

绑定链接可以使用 routerLink 这个指令,它的值是个字符串,如果是这样情况,可以直接把字符串类型的值放在这组双引号里面,然后再去掉 routerLink 周围的方括号。

预览

然后回到浏览器预览一下,先随便打开一个地址,然后按一下 Header 上的标题,链接的地址是应用的根,不过这是一条重定向类型的路由,它会把用户重定向到 posts 这个地址。

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



8)定义通配符路由(wildcard)

通配符路由可以匹配所有地址,一般我们可以用它显示页面找不到的提示,就是如果用户访问的地址在路由里不存在,就会显示一个 404 的提示。

回到项目,在定义路由之前,可以先去创建一个组件,在项目下面,执行 ng generate 生成一个 component,

# ng g c core/components/page-not-found

放在 core/components 里面,名字是 page-not-found 。

然后打开刚才创建的这个组件的模板文件,去掉里面的内容,先用一个标题元素,文字是 404,再添加一个段落,文字是 This page doesn't exist.

再去定义一条通配符路由,打开 AppRoutingModule,在 routes 里面,添加一条路由,路由的 path 是两个星号,表示这是一个通配符路由,路由对应的 component 设置成 PageNotFoundComponent 。

预览

到浏览器上试一下,可以访问一个应用里不存在的路由地址,页面上显示的就是 PageNotFoundComponent 组件的视图。

注意这个通配符路由要在所有路由的最下面,可以这样再试一下,把这条路由放在所有路由的最上面。然后回到浏览器 ,现在你会发现,访问所有地址的时候都会显示 PageNotFoundComponent 组件的视图。

这是因为,Angular 的路由匹配了第一次以后,就不会继续匹配其它的了。所以定义这些路由的时候,这个顺序很重要,这个通配符可以匹配所有地址,所以要把它放在最后。这样其它的路由才有机会被匹配到。

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


9)用路由模块管理路由(Routing module)

应用的路由相关的配置可以直接放在应用的根模块里,也可以单独创建一个路由模块,比如在我们这个应用里,有个 AppRoutingModule 模块,里面定义了几条路由。

或者我们也可以为每一个功能模块去创建一个对应的路由模块。比如在这个 AppRoutingModule 里,有两条路由跟 Post 相关,所以可以在 Post 模块里再添加一个路由模块,在这个路由模块里管理跟 Post 相关的一些路由。

先去创建一个新的模块,用 ng ,generate 一个 module,放在 modules/post 里面,模块的名字是 post-routing,后面加上一个 --module 选项,设置一下把这个要生成的模块放在哪个模块里面,这里应该是 post 模块。最后可以再用一个 --flat 选项,这样生成的这个 PostRoutingModule 不会单独放在一个目录的下面,直接会放在 modules/post/ 这个目录里面。

# ng generate module modules/post/post-routing --module post --flat

回到项目,先打开 PostModule 这个模块,你会发现,在这个模块的 imports 里面,已经导入了 PostRoutingModule,这个模块是刚才我们用命令生成的。

这个模块里还导入了 AppRoutingModule,可以去掉它,再删除掉文件顶部导入这个模块的代码。

然后打开 PostRoutingModule 模块, 在模块里添加一个 routes,它的类型是 Routes,这个 Routes 来自 @angular/router 包。

打开 AppRoutingModule 模块,可以剪切一下在这个模块里定义的这两条跟 Post 相关的路由,这样在这个模块里导入的这两个 Post 组件也就用不到了,可以去掉它们。

回到 PostRoutingModule 模块,把剪切的路由粘贴到这里,这里需要再导入路由需要的两个模块,鼠标放在这个模块的名字的上面,command + . 选择要导入的模块。同样的方法处理一下,下面这个组件,导入需要的组件。

在 Routing 模块里,一般不需要 declarations ,可以去掉它,然后在 imports 里面,要导入 RouterModule,这里要用一下它上面的 forChild 方法,然后把 routes 交给它。

注意在 AppRoutingModule 里,用的是 RouterModule 的 forRoot 方法,在其它的路由模块里,都需要使用 forChild 方法配置路由。

在 Routing 模块里,还需要导出这个 RouterModule 。

预览

到浏览器再预览一下,你会发现页面显示的是 404 ,这是因为定义路由的顺序很重要,回到项目,打开 AppModule 模块,在它的导入里,AppRoutingModule 会出现在 PostModule 的前面,这里要做一下调整,把这个 AppRoutingModule 放在最后这个位置上。

再到浏览器上预览一下,现在应用的路由功能就正常了。这个内容列表页面的路由,还有单个内容页面的路由我们是在一个单独的 Routing 模块里定义的。

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


10)功能模块的路由模块(RouterModule.forChild)


打开项目里的 AppRoutingModule 模块,在这个模块里定义的路由,有一条属于 User 模块,就是这个地址是 register 的路由。跟 User 模块相关的路由可以单独放在它自己的路由模块里。

在终端给项目生成一个模块,ng generate,生成一个 module,放在 modules/user 里面,名字是 user-routing,添加一个 --module 选项,这个模块属于的模块是 user 模块,再用一个 --flat 选项,表示不把这个要生成的模块单独放在它自己的目录里面。

# ng g m modules/user/user-routing --module user --flat 

回到项目,剪切一下在 AppRoutingModule 里定义的这条路由,然后删除掉文件顶部导入的路由需要的组件。

找到我们刚才给 User 模块生成的路由模块,user 目录下的这个 user-routing.module.ts 。

在这个模块里定义一个 routes,它的类型是 Routes,值是一个数组,然后把刚才剪切的路由定义放在这里。选中路由对应的组件,command + . 选择导入这个模块。

Routing 模块里不需要 declarations ,模块的 imports 里面,要导入 RouterModule,用一下 forChild 方法,把路由的定义交给它。这里就是 routes。

这个模块还需要导出这个 RouterModule,添加 exports,要导出里,添加一个 RouterModule 。

预览

回到浏览器,访问一下 register 这个地址,打开的就是一个注册用户用的表单。这条路由现在我们是在 User 模块的路由模块里定义的。

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

11)路由链接与路由链接的活动状态(routerLink, routerLinkActive)


Header 组件上的这两个导航项目还没有链接,下面可以给它们绑定一个链接地址。回到项目,打开 HeaderComponent 组件的视图文件。

给这个 a 设置链接地址不能直接使用元素的 href 属性,这里要用 Angular 里的 routerLink 指令。用一下这个 routerLink 指令,它的值是一个字符串,先用一组双引号,里面再用一组单引号,然后是字符串的值,比如 posts。

如果指令的值是字符串,可以使用一个简单的形式,直接把指令的值放在这组双引号里面,再去掉指令周围的方括号。

同样再处理一下,下面这个 Register,routerLink ,值是 register 。

预览

回到浏览器可以先试一下,点击 Header 组件上的 Posts ,打开的就是这个 posts 地址,点击 Register,打开的就是 register 。

激活

导航项目在活动状态下的时候我希望它有不一样的样式,可以使用 routerLinkActive 指令,给活动状态下的元素添加一些自定义的 CSS 类。

在这个 a 标签里面,用一个 routerLinkActive,因为它的值是字符串,所以使用这个指令的时候可以不加方括号。值是 active 。再去处理一下 Register 这个链接 ,同样用一个 routerLinkActive,值是 active。

这样这个链接在活动状态下,会在它上面绑定一个 active 这个类。

打开组件的样式表,可以设置一下这个类的样式,nav 下面的 a.active,设置一下文字的颜色,颜色可以是黑色。

预览

再回到浏览器,检查一下这个链接元素。现在它是活动状态,因为当前打开的页面就是 posts,所以在这个元素上会出现一个 active 类,我们在组件的样式表里为这个类设置的样式就是让文字的颜色变成黑色。

点击这个 register 链接,你会发现刚才在 posts 链接上的 active 类就不见了,因为当前活动的链接是这个 register 。

routerLinkActiveOptions

打开 posts,这个链接又变成了当前活动的状态,再打开一个内容项目页面,这个导航链接仍然是活动状态。因为当前页面的地址里包含 posts 。这个行为可以修改一下。

回到项目,在这个 posts 链接元素上,用一个 routerLinkActiveOptions 指令,它的值是一个对象,把 exact 设置成 true 。意思就是只有当地址是 posts 的时候,这个链接才会是活动状态。

再到浏览器上试一下,打开 posts ,链接是活动状态,再打开一个内容页面,这次这个 posts 链接就不会再是活动状态了。因为我们把它的 routerLinkActiveOptions 的 exact 设置成了 true 。

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


12)用代码导航到指定的地址(router.navigate)


在 Router 里面有一些 Navigation 还有处理地址的功能。在这个内容详情页面上,我们可以添加一个 Back 按钮,按一下这个按钮可以返回到内容列表页面。

回到项目,先打开 PostDetailsComponent 组件,在这个内容详情组件里面添加一个 button ,按钮文字是 Back,给这个按钮绑定一个 click 事件,点击它的时候执行 gotoPosts 这个方法。

然后再打开这个组件,在组件里添加需要的事件处理方法,名字叫 gotoPosts,这个方法的功能就是导航到指定的地址上。

这里需要用到 Router 提供的功能,先把它作为这个组件的依赖注入进来,在组件的 constructor 方法里面,添加一个 private router,它的类型是 Router。这个 Router 来自 @angular/router 。

然后在 gotoPosts 方法里面,用一下 this.router 上的 navigate 这个方法,它的第一个参数是个数组,数组里的第一个项目可以是一个地址,比如 /posts 。

预览

回到浏览器可以再试一下,打开一个内容页面,页面上会显示一个 Back 按钮,点击这个按钮,触发 click 事件,我们监听了这个事件,要做的事情是执行组件里的 gotoPosts 方法。在这个方法里用了 Router 上的 navigate 方法,打开了一个特定的地址,就是 /posts 。

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


13)使用路由的可选参数(Optional parameters)


在内容列表里打开一个内容项目,注意现在页面的地址是 posts/ 后面这个数字是当前要显示的这个内容项目的 id 号。posts 斜线后面的这个 id 是这条路由里的一个必填的参数。因为组件需要用到这个参数的值才能正常显示需要的内容。

在路由地址里可以包含一些可选参数,路由里的这些可选参数是用分号分隔开的,参数的名字,等号右边是参数的值。在组件里我们也可以得到这些可选参数的值。

回到项目,打开 PostDetailsComponent 组件的视图文件,把 entity 这个值交给 gotoPosts 方法。然后打开这个组件, 找到 gotoPosts,让这个方法接收一个 entity 参数,类型是 Post 。

方法里用了 Router 上的 navigate 方法,打开 /posts 这个地址,在这个数组里再添加一个对象项目,里面添加一个 id 属性,对应的值是 entity 里的 id 。

预览

回到浏览器可以预览一下,先打开一个内容详情页面,然后按一下 Back 按钮,打开的是 posts ,这次地址里会包含 id 参数,它的值就是刚才打开的内容的 id 号。下面我们使用这个可选的 id 参数去做一些事情,比如在这个内容列表里高亮显示上一个打开的内容项目。

ActivatedRoute

回到项目,打开 PostComponent 组件,先在组件里注入一个 ActivatedRoute,在构造方法里,添加一个 private route,类型是 ActivatedRoute 。

然后在组件的 ngOnInit 生命周期方法里,订阅一下路由的 paramMap ,this.route.paramMap,用一下 subscribe 方法,给它一个方法参数,方法有个 params 参数 。

在这个组件里可以添加一个属性,名字是 selectedId ,类型是 number 。

然后在这个给 subscribe 提供的方法里,设置一下 this.selectedId 的值,它的值可以用一下 params.get ,得到 id 参数的值。在前面加上一个加号,把得到的 id 参数的值转换成数字类型的。

视图

然后打开这个组件的视图文件,在这个 app-post-item 上面,绑定一个 CSS 类,class.selected ,绑定这个类要根据一个条件,条件是 entity.id 等于组件里的 selectedId 。

样式

再打开应用的全局样式表,在这个样式表里,设置一下 .selected 这个类下面的 .list__item 的样式,把它的 background 设置成 #f8f8f8 。

上面这个 .list__item 的样式可以再稍微改一下,用 padding 设置一个统一的内边距,大小是 16px 。

预览

回到浏览器,可以预览一下。打开内容列表,按一下 Back 按钮,返回以后,在地址里会包含一个可选的 id 参数,它的值是刚才打开的内容项目的 id 号。组件里会根据这个 id 参数的值,动态的在对应的 PostItemComponent 组件上面添加一个 selected 类。这样就会在列表里高亮显示这个内容项目。

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

14)演示模块(DemoModule)


在应用里可以创建一个演示模块,在里面演示 Angular 框架提供的一些功能。在终端,执行 ng generate 生成一个 module,

模块放在 modules 里面,名字叫 demo ,我希望生成的这个模块可以有一个单独的 Routing 模块,所以在这个命令里面,再加上一个 --routing 选项。再用 --module 选项,指定一下这个生成的模块要放在哪个模块里。这里应该是应用的 app 模块。

# ng g m modules/demo --routing  --module app

执行一下。

回到项目,找到刚才生成的模块,在 app,modules 的 demo 目录的下面,有一个 demo.module.ts ,这个文件里定义了这个演示模块。

另外在这个目录里还有一个 demo-routing.module.ts,这是一个路由模块,因为在生成 Demo 模块的时候我们用了一个 --routing 选项,所以会自动生成这个路由模块。

在 Demo 模块里,已经导入了这个 DemoRoutingModule 模块。

另外,命令还会自动更新一下 AppModule 模块,在这个模块里,已经给我们自动导入了 DemoModule。这是因为在执行生成模块的命令的时候,用了一个 --module 选项,指定了要生成的模块要在哪个模块里导入。

注意这个 DemoModule 模块里包含了它的路由模块,一会儿我们会在这个路由模块里添加几条路由,这里需要把应用的路由模块,也就是这个 AppRoutingModule 放在所有模块的最下面,因为在这个路由模块里定义了一条通配符类型的路由,如果把这个模块放在 DemoModule 的前面,在 DemoMoudle 的路由模块里定义的路由就不会被匹配。

所以要把这个 AppRoutingModule 放在所有导入的模块的最下面。

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


15)子路由(Child Routes)


在终端,先在项目的 demo 模块里添加两个组件,ng generate ,生成一个 component ,放在 modules/demo 里面。

# ng g c modules/demo

再生成一个组件,放在 modules/demo/child-routes 里面。

# ng g c modules/demo/child-routes

回到项目,打开 Demo 模块的路由模块,DemoRoutingModule,在这个路由模块里定义两条路由,放在这个 routes 里面,路由的 path 是 demo ,对应的 component 设置成 DemoComponent 。

预览

回到浏览器,在地址栏里输入 demo 这个地址,现在显示的就是 DemoComponent 组件的视图内容。

子路由

再回到项目,在这条 demo 路由里面,可以添加一些子路由,在这条路由的定义里面,用一个 children ,它是一个数组,里面是一些路由的定义。添加一个子路由, path 可以设置成 child-routes,因为这条路由是 demo 的一个子路由,所以它的地址应该是 demo/child-routes。

这条路由对应的 component 是 ChildRoutesComponent。

预览

再到浏览器上试一下,在地址栏里输入 demo/child-routes,这里显示的仍然是 Demo 组件的视图,并没有显示 ChildRoutesComponent 组件的视图内容。

这是因为子路由的组件显示的地方是它的父路由组件视图里的 RouterOutlet。

RouterOutlet

回到项目,打开 Demo 组件的视图,在这个视图里要添加一个 router-outlet。 在这里的 router-outlet 这个地方,会显示 Demo 的子路由的组件。

预览

可以再回到浏览器预览一下,现在访问 demo/child-routes 这个地址的时候,页面上就会显示 child-routes 这条路由对应的 ChildRoutesComponent 组件的视图内容了。

显示这个组件的地方是在 Demo 组件视图里添加的 router-outlet 那里。

Header

再打开 Header 组件的视图文件,在这个导航里可以再添加一个链接,一组 a 标签,文字是 Demo,在这个 a 标签上用一个 routerLink,地址是 demo,再添加一个 routerLinkActive,激活状态下要添加的 css 类是 active。

现在,应用的 Header 上面,会有一个 Demo 链接,点击这个链接打开的就是 Demo 组件视图。

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


16)演示组件的视图(DemoComponent)


打开 Demo 里的 ChildRoutesComponent 组件的视图文件,修改一下这个视图内容,一组标题元素,文字是 Child routes,下面再用一个段落标签,文字是 This is a child route.

然后再去修改一下 Demo 组件的视图文件,一组 div,上面加上一个 demo 类,这块视图可以分成两栏显示,一个 div,左边栏上添加一个 sidebar 。 下面再添加一个 div,主体内容上添加一个 content 类。

把 router-outlet 放在这个 content 里面。在这个 sidebar 里面可以添加一些链接,一组 a 标签,文字是 Child routes。 在这个 a 标签上用一个 routerLink,这个链接地址可以使用一个相对的地址,./ 表示当前位置,后面加上一个 child-routes。

routerLinkActive ,值是 active 。

样式

下面可以再去设计一下这个视图的样式,打开组件自己的样式表。先设置一下 .demo 的样式,把它的 display 设置成 flex,height 可以设置成 100vh。

再设置一下 .sidebar 的样式,先用 border-right 添加一条右边的边框,1个像素的实线,颜色是 #eee。然后可以用 margin-left ,值是 -32px,再用 margin-top,值也是 -32px 。

然后设置一下 .sidebar 里的 a 标签的样式,display 设置成 block ,padding,上下是 8px,左右是 24px。用 color 设置一下文字的颜色,rgba 颜色是黑色,不透明度是 0.7。

下面再设置一下活动状态下的链接的样式,.sidebar a.active,用 background 设置一下背景颜色,#f8f8f8,再用 color 设置一下文字的颜色,设置成黑色。

再给 .content 添加点样式,里面用 padding-left,左边的内边距设置成 32px。

预览

回到浏览器,可以预览一下现在的 Demo 组件视图,按一下视图左边栏上的链接,可以显示 Demo 的子路由视图里的内容。


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

17)二级路由与有名字的 Outlets


在应用的 AppComponent 的视图里,添加了一个没名字的 Outlet ,在这里会显示应用的路由对应的那个视图里的内容。一个模板里面只能有一个不带名字的 Outlet。

下面我们可以试一下带名字的 Outlet,应用的二级路由一般都会在这些有名字的 Outlet 里面显示。在这个 AppComponent 组件的视图文件里可以添加一个带名字的 Outlet。一组 router-outlet,在它上面用一个 name,给这个 Outlet 起个名字,比如 popup 。

然后可以再去定义一条二级路由,让路由组件在这个 popup 里面显示。

MessageBoxComponent

在终端给项目生成一个新的组件,ng generate ,生成一个 component,放在 core/components 里面,组件的名字是 message-box。

# ng g c core/components/message-box

回到项目,找到刚才生成的这个组件的模板文件,修改一下里面的内容。一个 div,上面加上 message-box 这个类,里面先包装一个标题,文字是 Message box,下面再添加一个段落文字,The component displayed in a outlet named popup。

路由

打开 AppRoutingModule 模块,里面添加一条新的路由,路由的 path 可以设置成 message,路由对应的组件就是刚才生成的 MessageBoxComponent。二级路由需要再用 outlet 设置一下对应要显示在哪个 outlet 里面,这里可以把它设置成 popup。

链接

然后再打开 HeaderComponent 组件的模板文件,在导航里面添加一个新的项目,一组 a 标签,文字是 Message,绑定一个 routerLink,它的值是一个链接参数数组,数组里有个对象,里面添加一个 outlets,它的值又是一个对象,然后先是 Outlet 的名字,比如 popup,它的值又是一个链接参数数组,里面添加一个 message 路由。

预览

回到浏览器可以试一下,按一下导航上的 Message,会打开 message 这个二级路由,这样就会在 AppComponent 组件的模板文件里的名字是 popup 的 outlet 里面,显示 Message 路由的组件。

注意地址栏里的地址,会在当前的地址后面出现一个括号,然后是 outlet 的名字,还有对应的路由地址。

现在不管我们打开哪个页面,这个 MessageBoxComponent 都会在 popup 这个 outlet 这里一直显示。

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



18)MessageBoxComponent 样式


下面再去设计一下这个组件的样式,回到项目,打开 MessageBoxComponent 组件的样式文件,设计一下 .message-box 类的样式,先把它的 position 设置成 absolute,用 bottom 设置一下底部的位置,50px,再用 right 设置一下右边的位置,也可以是 50px。

用 height 设置一下它的高度,大小是 200px,width 可以设置一下宽度 ,大小也是 200px。 再用 padding 添加点内边距,大小是 32px。

用 background 设置一下它的背景颜色 ,用白色。 border-radius 圆角的大小可以是 5px,再添加一个边框的样式,1px 的实线,颜色是 #eee。 最后可以再用 box-shadow 给元素添加点阴影的效果。0 34px 47px 0 ,颜色可以用 rgba,颜色是黑色,不透明度是 0.06 。

最后再回到浏览器预览一下,打开应用的任何页面,这个 MessageBoxComponent 都会在它原本的位置上显示。

链接

下面可以在这个演示页面的边栏上添加一个链接,地址就是在 popup 这里打开 message 。

回到项目,打开 Demo 组件的模板文件,在这个 sidebar 里面,可以再添加一个链接,名字是 Named outlets。

用一下 routerLink,它的值是一个链接参数数组,第一个项目可以设置成斜线,第二个项目是一个对象,里面有个 outlets,它的值是个对象,popup 是 outlet 的名字,值是个链接参数数组,里面添加一个 message 。

预览

到浏览器上预览一下,关掉二级导航,可以去掉这个二级导航地址,然后再按一下演示页面边栏上的这个 Named outlets,会在 popup 这个位置上打开 message 。

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


19)清除二级路由


在这个 MessageBox 组件上,可以添加一个按钮,按下这个按钮可以清除掉在 popup 上打开的二级路由。回到项目,先打开 MessageBoxComponent 组件的模板文件,在这个模板文件里添加一组 button ,按钮文字是 Close。

在这个按钮上绑定一个 click 事件,点击按钮,执行 closePopup 方法。

然后打开 MessageBoxComponent 组件,在这个组件里要添加一个方法,名字是 closePopup ,方法做的事情就是清除 popup 上的二级路由。这里需要用到 Router 提供的功能,先把它作为这个组件的依赖注入进来。

在组件的 constructor 里面,添加一个 private router,类型是 Router,注意要在文件顶部导入这个 Router,它来自 @angular/router 。

在这个 closePopup 方法里,用一下 this.rotuer.navigate 方法,给它一个数组,里面有个对象,添加一个 outlets,它的值是个对象,把 popup 的值设置成 null。

预览

再回到浏览器,现在,这个 MessageBoxComponent 上面,会出现一个 Close 按钮,按一下它,可以清除掉在 popup 这个 outlet 上打开的路由。

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


普通分类: