前言
这星期主要实现了一个搜索功能,,便于用户在选择项比较多的时候快速选择自己想要选的那个。
防抖
本着是一个隐藏的搜索框,如果在蹦出搜索框的同时右边有一个提交按钮的话会显得比较突兀,也是本着让用户少点一次的原则,就想做成一个类似于搜索提示的效果,这里用到了防抖机制。
我们希望当我们在搜索框中输入关键字时,系统能够自动搜索。但是系统无法判断我们输入到什么时候是他想要的关键字。这是就用到了防抖,通过搜索框内容改变的时间判断是否开始搜索,当一段时间内搜索关键字不改变时,开始调用搜索方法。当搜索关键字改变时,重置时间。
比如我们搜索河北工业大学
在不加入防抖时,过程是这样的:
“河” -- 请求1次后台(无用功)
“河北” -- 请求1次后台(无用功)
“河北工” -- 请求1次后台(无用功)
“河北工业” -- 请求1次后台(无用功)
“河北工业大学” -- 请求1次后台(用户想要的)
在我们加入防抖时,过程是这样的:
“河” -- 不请求后台
“河北” -- 等一秒,请求1次后台,但是搜索后的内容还是很多,继续输入
“河北工” -- 不请求后台
“河北工业” -- 不请求后台
“河北工业大学” -- 一秒后,请求1次后台(用户想要的)
具体到代码中,我们使用(input)事件判断搜索框内容变化,当内容变化时,会调用指定方法。
<input *ngIf="this.bindCourseSearch" (input)="search()" type="text" class="form-control search" placeholder="请输入课程名称或代码" [formControl]="courseCodeOrName"/>
同时c层
searchSubject: Subject<string> = new Subject<string>();
ngOnInit() {
...
this.searchSubject.asObservable().pipe(debounceTime( 1000))
.subscribe(() => {
this.codeOrName = this.courseCodeOrName.value;
});
}
search(): void {
this.searchSubject.next();
}
更多关于截流与防抖的应用请看这篇文章:Rxjs防抖与节流在项目中的应用
搜索速度
搜索往往面对很多数据,如何提高搜索速度也是重要的一环
减少请求后台次数
每请求一次后台,便会花费一些时间,所以我们要尽可能的减少请求后台次数。
如果不涉及到分页的话,我们请求一次所有数据后,在前台保存所有数据,以后关键字变更直接调用前台所有数据,减少请求后台所有数据。
/** 用于查询遍历,全部的专业课 */
courseClone: Array<Course>
减少遍历次数
我们在前台直接处理所有数据免不了进行遍历进行过滤,多次遍历也会影响搜索时间。
比如说,我们搜索课程有多个条件,在某一学院下名称或或者代码包含关键字的课程。一开始仿写写好的过滤学院条件代码去写过滤名称或代码的代码。然后先过滤一遍学院,再过滤一遍名称或代码。如果同时过滤二者需要很多判断,防止在空指针,很复杂。所以进行了两次过滤。但是我没有考虑到在v层显示其实也是一遍遍历。
我们可以运用v层的一遍遍历,去进行名称或代码过滤,过滤掉的加个*ngIf
不显示即可。
<ng-container *ngIf="getAllByCodeOrName(_course, state.codeOrName)">
<input class="form-check-input" id="course_{{_course.id}}" type="checkbox" [checked]="state.checkedMap.get(_course.id)"
(change)="change(_course.id)">
<label class="form-check-label" for="course_{{_course.id}}">{{_course.code}} {{_course.name}}</label>
</ng-container>
但是涉及到分页不建议这用ngif隐藏,这样会造成一页3条数据一页4条数据的情况。
补充
关于ng-container
<ng-container></ng-container>
理解为指令的宿主,并无实际含义
举个例子
我们无法在一个div中添加两个*ngif
判断
<!-- Can't do this -->
<div *ngIf="todos" *ngFor="let todo of todos">
{{ todo.content }}
</div>
这时候我们想到用两个div标签
<div *ngIf="todos">
<div *ngFor="let todo of todos">
{{ todo.content }}
</div>
</div>
但是,这样写多了一个无用的div,我们还可以这样写
<ng-container *ngIf="todos">
<div *ngFor="let todo of todos">
{{ todo.content }}
</div>
</ng-container>
ng-container并不会添加无用的标签。
参考:Angular: The ng-container Element
总结
一个好的项目必定伴随着一段优秀的代码,一段优秀的代码不仅是代码量少,也是时间复杂度低。这需要我们对实现的功能进行重构。一个功能不是实现就可以了,还要实现好。
感谢潘老师的指导。
版权声明
本文作者:河北工业大学梦云智开发团队 - 赵凯强
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。