前言
- 因为项目需求,需要实现一个搜索功能,之前看Angular官方文档的时候,记得有相同的实现,也没多想,心想着既然是官方文档,应该代码质量也是有保证的,所以就照着官方例子写了。然而,事情并没有想象中那么简单。
1.代码
<div id="search-component">
<h4>Hero Search</h4>
<input #searchBox id="search-box" (keyup)="search(searchBox.value)" />
<div>
<div *ngFor="let hero of heroes | async"
(click)="gotoDetail(hero)" class="search-result" >
{{hero.name}}
</div>
</div>
</div>
search(term: string): void {
this.searchTerms.next(term);
}
ngOnInit(): void {
this.heroes = this.searchTerms
.debounceTime(300) // wait 300ms after each keystroke before considering the term
.distinctUntilChanged() // ignore if next search term is same as previous
.switchMap(term => term // switch to new observable each time the term changes
// return the http search observable
? this.heroSearchService.search(term)
// or the observable of empty heroes if there was no search term
: Observable.of<Hero[]>([]))
.catch(error => {
// TODO: add real error handling
console.log(error);
return Observable.of<Hero[]>([]);
});
}
2.问题
- 实例代码中实现的功能是在搜索框中输入搜索条件,触发一个keyup事件即可通过HTTP发送搜索请求,不像之前项目中的搜索,输入完搜索条件还需要点击搜索按钮,这也算是Angular数据绑定好处吧。
- 但是,真相是绑定的(keyup)事件并没有每次都按照预期的运行,在测试功能的过程中,居然发现输入值后搜索不了,一检查keyup事件居然没有触发,虽然概率大概是20%左右,但是出了问题总要解决啊。
3.解决方案
- 然后就去Stack Overflow上寻找答案,居然还真有,解决方法在此,本来还以为是自己代码写的有问题,然而并不是。
- 解决方案:
// HTML
<input [(ngModel)]="searchBox" id="search-box" (keyup)="search(event)"/>
// Compoenet
searchBox: string // declare before constructor into your component
// declare after constructor into your component
@HostListener('document:keyup', ['$event'])
search(event: KeyboardEvent): void {
this.searchTerms.next(this.searchBox);
}
- 解释一下,该解决方案的意思是,把搜索框的值进行双向绑定,然后使用一个HostListener来监听文档中的keyup事件,就是每次触发keyup事件都调用search()函数,按照解决方法试了一下,发现真的可以,按道理应该到此就圆满结束。
- 但是并没有,填完一个坑总是又有一个新的坑。正如上文所言,上述解决方案中的HostListener是用来监听整个文档中的keyup事件,这就很尴尬了,项目需求中是同一个页面中两个搜索框,只要任何有一个keyup触发,都会调用该搜索功能,这他么还得力,每次keyup事件调用一次,这显然是一个更大的坑啊!
- 好忧桑,怎么办,如何解决?
4.最终解决方案:
- 后来想了想,算了吧,这个绑定keyup事件功能就不用了,不就是输入完自动搜索嘛,不要了。果断加了个搜索按钮,然后绑定(click)事件,每次输入完毕后去点一下,实现完毕之后测试了几十次,发现果然没有再出现不能触发事件的问题了。
总结
- 写代码还是要自己动手实践,实践中遇到问题是好事情,通过解决这些问题,才能锻炼和提升自身能力。
- 前端Angular打怪升级中,业余写写学习笔记,记录并分享学习心得,欢迎骚扰讨论技术问题。