本节中,我们来共同完成前台对接后台前的最后准备工作。 # 初始化 ## C层 在C层中,我们添加一个`onSubmit`方法,用于V层点击`提交`按钮时触发。 TeacherAddComponent ```js export class TeacherAddComponent implements OnInit { name: string; username: string; email: string; sex: boolean; ngOnInit(): void { } /** * 将要保存的教师信息提交给后台 * 当声明方法为public(此关键字可省略)时,相当于绑定到了V层,V层中可以进行调用或是绑定操作。 */ public onSubmit(): void { console.log('点击提交按钮'); ➊ } } ``` * ➊该方法被成功触发时,向控制台打印测试内容。 ## V层 在表单中,使用`ngSubmit`绑定表单单提交时触发的方法。 teacher-add.component.html ```html <pre>{{name}} {{username}} {{email}} {{sex}}</pre> <form id="teacherAddForm" (ngSubmit)="onSubmit()"> ➊ ``` * ➊ 当表单提交时,触发C层的`onSubmit`方法 ## 测试 ![](https://img.kancloud.cn/64/99/64998d00d838fea64c721e544b477ad3_706x502.gif) # 向后台发送请求 ```js import {HttpClient} from '@angular/common/http'; constructor(private httpClient: HttpClient) { ★ } /** * 将要保存的教师信息提交给后台 * 当声明方法为public(此关键字可省略)时,相当于绑定到了V层,V层中可以进行调用或是绑定操作。 */ public onSubmit(): void { const url = 'http://localhost:8080/Teacher'; const teacher = { ➊ name: this.name, ➋ username: this.username, email: this.email, sex: this.sex }; console.log(teacher); ➌ this.httpClient.post(url, teacher) ➍ .subscribe(function () { ➎ console.log('添加成功'); }, (response) => { ➏ console.error('请求发生错误', response); }); } ``` * ★ 不解释 * ➊定义要传入后台的数据对象,该对象起名为teacher,对象中有4个属性分别为name,username,email,sex。属性的值分别为当前V层表单中用户输入的值(数据双向绑定)。 * ➋用当前组件的name值(即V层用户输入的值)来给teacher对象的name属性赋值。 * ➌开发测试信息,为了在控制台中查看是否正确的为teacher赋值了。 * ➍使用httpClient对象,向`url`地址发起`post`请求,请求的内容为`teacher`。 * ➎匿名函数,当请求成功时调用此方法**由于前面我们讲过的原因,此方法将在后面弃用**。 * ➏匿名箭头函数,当请求失败时调用此方法。 # 测试 ![](https://img.kancloud.cn/15/ab/15ab89dc8eefbaa6fdad3bae3a5e12de_706x502.gif) 请求成功的发出,由于后台无相关功能的原因,触发了我们定义的请求发生错误代码,且控制台打印的`teacher`信息正确,符合预期。 # 本节小测 ## 请思考 我们前台提到过一个原则,即:规避在代码直接输入字符串。但`http://localhost:8080/Teacher`此字符串我们却分别在`AppComponent`及`TeacherAddComponet`中分别写了一次,这显然违背了上述原则。如果并不需要考虑编码,你有什么解决的思想吗? > 程序员 = 拥有编程技能的工人;工程师 = 程序员 + 拥有编程思想的科技工作者。只有着重学习编程思想、反复练习编程技能,才能成为优秀的软件工程师。 ## 上节答案1 我们已经学习过了`ngFor`、`ngIf`、`ngModel`,请尝试总结在功能及使用方法上的异同点。 | 指令 | 功能 | 使用方法 | | --- | --- | --- | | ngFor | 按实际情况,复制宿主dom代码变成0行、1行或多行HTML代码 | 以`*`打头,使用方法与一般的dom属性相同 | | ngIf | 按实际情况,选择保留或移除宿dom | 以`*`打头,使用方法与一般的dom属性相同 | | ngModel | 不改变宿主dom的结构,获取(并设置)宿主dom的值 | 使用`([])`进行包裹 | > dom = Document Object Model 文档对象模块。在html,我们习惯性的称为html dom。可以简单的理解为某标签及包含的子标签(如有)。 ***** **总结:** 我们把改变dom结构的指令称为结构型指令,比如`ngFor`;把不改变dom结构的指令称为属性型指令,比如`ngModel`。 ***** ## 上节答案2 测试的方法有很多种,在这里给出其中的一种: V层 ``` <form id="teacherAddForm" (ngSubmit)="onSubmit()"> <div> <label for="name">姓名:</label> <input type="text" id="name" name="name" [(ngModel)]="name"/> </div> <div> <label for="name">测试姓名:</label> <input type="text" id="name1" name="name1" [(ngModel)]="name1"/> </div> <div> <button>提交</button> </div> </form> ``` C层 ``` export class TestComponent { name: string; name1: string; public onSubmit(): void { console.log(this.name); ➊ this.name1 = this.name; ➋ } } ``` * ➊ V层中的姓名变化后,点击提交按钮打印C层中name的值,打印的值同V层中的值相同,说明V层的表单变化时时影响了C层变量的值。 * ➋ 在C层中对变量name1赋新值,此时V层中对应的测试姓名表单中的内容时时发生了变化,说明C层中的变量值发生变化时,实时的传递给了V层。 # 参考文档 | 名称 | 链接 | 预计学习时长(分) | | --- | --- | --- | | 使用ngSubmit提交表单 | [https://www.angular.cn/guide/forms#submit-the-form-with-ngsubmit](https://www.angular.cn/guide/forms#submit-the-form-with-ngsubmit) | 2 | | 发起一个POST请求 | [https://angular.cn/guide/http#making-a-post-request](https://angular.cn/guide/http#making-a-post-request) | 5 | | HTTP 方法:GET 对比 POST(文章下面的笔记更精彩) | [https://www.runoob.com/tags/html-httpmethods.html](https://www.runoob.com/tags/html-httpmethods.html) | 10 | | 源码地址 | [https://github.com/mengyunzhi/spring-boot-and-angular-guild/releases/tag/step2.3.3](https://github.com/mengyunzhi/spring-boot-and-angular-guild/releases/tag/step2.3.3) | - |