本周写了登录方面的内容,理清了一些思路。
先写一下遇到的其他方面的问题:
问题一
【登录的实现】
文章图片
当时莫名就出现了这个.angular文件,结果push的时候报错:超出文件大小。
在.gitignore中忽略掉.angular后依旧上传。然后尝试着新建分支后把代码合一下再上传,但好像没有起作用。
最后解决方法是回退版本:
文章图片
选择相应的文件,右键点击git,然后show histroy ,选择需要回退到的分支后,reset current Branch to here,就可以回退到相应的版本。
问题二
文章图片
ng s的时候控制台报了这个错,看起来应该是循环注入报的错,但是不知道从何下手。组件名仅为t,而且文件位置也没有参考价值。最后解决方法是参考历史代码,
发现在app.module.ts中没有注入HttpClinentModule引起的。引入后运行正常。
文章图片
问题三
在想给路由id为1的参数的时候,控制台报错parmsSubject为null。
fit('should create', () => {
route.paramsSubject.next({id: 1});
...
});
文章图片
之后发现注入的RouterTestingModule引的angular库的,不是团队的库。
如果不用团队的库的话,解决办法是直接调用loadById方法测试。
文章图片
登录 大概画了一个流程图
文章图片
来一步步根据代码来理解一下。
一 V层通过submit提交from表单,并触发login方法
二 login方法中:调用userService.login()方法,并以构造的user作为形参。
const user = {
username: this.loginForm.get('username').value as string,
password: this.loginForm.get('password').value as string
};
this.userService.login(user)
.subscribe(next:() => {},error:() => {})
三 userService中的login方法:
login(user: { username: string, password: string }): Observable {
// 新建Headers,并添加认证信息
let headers = new HttpHeaders();
// 添加 content-type
headers = headers.append('Content-Type', 'application/x-www-form-urlencoded');
// 添加认证信息
headers = headers.append('Authorization',
'Basic ' + btoa(user.username + ':' + encodeURIComponent(user.password)));
// 发起get请求并返回
return this.httpClient.get(`${this.baseUrl}/login`, {headers})
.pipe(tap(data => this.setCurrentLoginUser(data)));
}
1.首先构造一个HttpHeaders。
2.给其添加 content-type.其中Content-Type 被指定为 application/x-www-form-urlencoded;其次,提交的数据按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL 转码。大部分服务端语言都对这种方式有很好的支持。例如 PHP 中, $_POST['title'] 可以获取到 title 的值,$_POST['sub'] 可以得到 sub 数组
3.
encodeURIComponent()方法对密码进行编码。
原因:如果密码字符串中包含了=或者&,那么势必会造成接收Url的服务器解析错误,因此必须将引起歧义的&和=符号进行转义, 也就是对其进行编码。
如将符号=,转义成%3D。
btoa() 方法用于创建一个base-64 编码的字符串,也就说将编码好的密码和账号拼一起进行btoa编码。
4.将构建好的header作为请求头,向后台发送get请求。
四:若请求成功 请求成功的情况下,后台会return一个user,在pipe管道下用tap方法作为data,调用方法,在userService中设置当前登录的user。
return this.httpClient.get(`${this.baseUrl}/login`, {headers})
.pipe(tap(data => this.setCurrentLoginUser(data)));
同时由于请求成功,并在步骤二中订阅了其变化,故会触发next回调函数
this.userService.login(user)
.subscribe(next:() => {},error:() => {})
在next回调函数中,通过navigateByUrl方法跳转到首页的url。登录成功。
this.router.navigateByUrl('url').then();
四:若请求失败 请求失败的情况下,后台会返回一个状态为401,类型为HttpErrorResponse的Observable。
return new Observable(subscriber => {
subscriber.error(new HttpErrorResponse({status: 401}));
subscriber.complete();
同时由于请求失败,并在步骤二中订阅了其变化,故会触发error回调函数
this.userService.login(user)
.subscribe(next:() => {},error:() => {})
error回调函数中:可以打印报错信息,并使errorInfo为登录失败,显示在v层。示意用户重新输入,
(response) => {
const errorCode = +response.headers.get('code');
const errorMessage = response.headers.get('message';
console.log(`发生错误:${errorCode}, ${errorMessage}`);
this.errorInfo = '登录失败,请检查您填写的信息是否正确';
总结
本周收获了登录方面的思路和细节,并理解了登录请求和RoutingModule以及依赖注入的代码逻辑。
推荐阅读
- Angular实现的增删改查
- angular版本更新与配置文件问题
- ng : 无法加载文件 C:\Users\Administrator\AppData\Roaming\npm\ng.ps1,因为在此系统上禁止运行脚本。
- Angular 变化检测详解
- angualr|angular规范
- Angular重要概念
- 微前端( Single-SPA框架)
- 解决angular单个页面只能加载一个ng-app的问题