前面的章节中,我们完成了教师的查看列表index、新增add以及编辑edit的功能。本节中,我们在教师列表中增加`编辑`按钮,用户点击该按钮后跳转到编辑界面,完成更新后再跳转回教师列表界面;增加`新增`按钮,点击后跳转至新增界面,完成新增后然后再回跳到列表界面。 **angular官方中文网把这种跳转功能称为`路由器链接`,对应的英文关键字为`router-links`,表示链接到某个路由。** # 编辑按钮 app.component.html ```html <td>删除</td> ✘ <td><a routerLink="/edit/{{teacher.id}}">编辑</a> &nbsp;&nbsp;删除</td> ✚ ➊ ``` * ➊ 使用routeLink来声明a标签跳转的地址,使用`{{teacher.id}}`来填充该teacher对象对应的id值 或者我们也可以这样使用: ```html <td><a [routerLink]="['/edit', teacher.id]">编辑</a> &nbsp;&nbsp;删除</td> ➊ ``` * ➊ 使用`[routerLink]`来替换`routerLink`,接收的值的类型为字符串,该字符串中标记了一个数组,数组的第一项为路由地址,第二项为路由参数。 > 在实际的项目中,当第一种方法无法满足我们的需求时,我们采用第二种方法。 ## 完成编辑后回跳 teacher-edit.component.ts ```js import {ActivatedRoute, Router} from '@angular/router'; constructor(private route: ActivatedRoute, private httpClient: HttpClient, private appComponent: AppComponent, private router: Router ①) { } /** * 提交表单 */ onSubmit(): void { this.httpClient.put(this.getUrl(), this.teacher) .subscribe(() => { console.log('更新成功'); this.appComponent.ngOnInit(); this.router.navigate(['/']); ➊ }, () => { console.error(`更新数据时发生错误,url:${this.getUrl()}`); }); } ``` * ① 引用Router。**注意:**前面我们引用的是`route 路由`,而现在我们引用的是`router 路由提供者`。 * ➊ 使用`router.navigate()`完成跳转,该函数接收的参数类型为`数组`,在数组中第一项指跳转的路由地址。 ## 测试 ![](https://img.kancloud.cn/66/e6/66e6cd9b5f3613ebf710b4c9852b9a8b_666x483.gif) 测试中我们发现虽然实现了由列表页向编辑页进行跳转,编辑完成后也的确是跳转回了首页。但是如果我们在编辑的页面中点击编辑按钮时,虽然URL如期发生了变化(说明路由器链接是成功的),但编辑页面的内容却未发生任何变化。这明显是一个BUG。 > 如果在软件的测试过程中,你总能想出各种可能导致BUG的测试用例。这说明你足够用心的同时天生就具备了软件开发工程师的灵魂。 **为什么会这样呢?**猜测原因的同时,我们增加些测试代码: teacher-edit.component.ts ```js ngOnInit(): void { console.log('组件初始化'); ➊ this.httpClient.get(this.getUrl()) ``` * ➊ 当组件被初始化时,在控制台打印信息。 ![](https://img.kancloud.cn/47/8b/478b39ec2e848523c1024af77abe9af1_678x373.gif) 通过测试我们猜测:在进行组件调用时,如果当前的界面存在此组件,则直接使用此组件而不在重新渲染。所以当在编辑界面中编辑其它的数据时,教师编辑组件中的`ngOnInit`方法没有被重新调用,导致了编辑界面中的数据未发生任何变化。此时可能你想到了在数据添加的小节中,我们添加完数据后教师列表页并没有实时的更新,最后我们使用的方法是在教师新增组件中注入了教师列表组件(AppComponent),并手动的调用了教师列表组件的`ngOnInit`方法(在教师编辑界面我们也是这么处理的)。同时,前面我们还讲过可以在子组件中直接注入父组件,因为子组件依赖于父组件,子组件存在时说明父组件必然存在;但无法在父组件中注入子组件,因为父组件存在时子组件不一定存在,这就决定了我们无法用“在App组件中调用TeacherEdit组件中的ngOnInit来强制子组件执行该方法(实际上即使可能这样做,也是无济无事的)”。 在下个小节中,我们将使用一种新的设计思想 -- **观察者模式**来解决这个问题。 # 参考文档 | 名称 | 链接 | 预计学习时长(分) | | --- | --- | --- | | 路由器链接 | [https://www.angular.cn/guide/router#router-links](https://www.angular.cn/guide/router#router-links) | 2 | | 路由参数 | [https://www.angular.cn/guide/router#route-parameters](https://www.angular.cn/guide/router#route-parameters) | 5 | | 源码地址 | [https://github.com/mengyunzhi/spring-boot-and-angular-guild/releases/tag/step2.4.6](https://github.com/mengyunzhi/spring-boot-and-angular-guild/releases/tag/step2.4.6) | - |