Angular自定义Debounce指令实现搜索输入延迟展示结果失效如何解决
问题根因
- 你的防抖指令当前监听的是
click点击事件,和输入框输入文本的触发事件完全不匹配,输入时不会触发指令逻辑 - 指令没有对外暴露防抖后的输出事件,组件无法拿到指令处理后的结果
- 现有组件逻辑依然是直接监听
valueChanges触发搜索,完全没有用到指令的防抖能力
修复步骤
1. 重写防抖指令 debounce.directive.ts
调整监听事件,新增Output输出防抖后的值:
import { Directive, Input, Output, EventEmitter, OnInit, OnDestroy, HostListener } from '@angular/core'; import { Subject, Subscription } from 'rxjs'; import { debounceTime, distinctUntilChanged } from 'rxjs/operators'; @Directive({ selector: '[appDebounce]' }) export class DebounceDirective implements OnInit, OnDestroy { @Input('appDebounce') debounceTime = 500; // 新增输出事件,对外抛出防抖后的值 @Output() debounceChange = new EventEmitter<string>(); private input$ = new Subject<string>(); private subscription: Subscription; ngOnInit() { this.subscription = this.input$ .pipe( debounceTime(this.debounceTime), distinctUntilChanged() ) .subscribe(value => this.debounceChange.emit(value)); } // 监听input输入事件,输入时触发逻辑 @HostListener('input', ['$event.target.value']) onInput(value: string) { this.input$.next(value); } ngOnDestroy() { this.subscription.unsubscribe(); } }
2. 修改 search.component.html 模板
绑定指令的输出事件,替换原来直接依赖formControl的逻辑:
<div id="search-component"> <label class="search-label">Todo Search</label> <input class="search-input" placeholder="Search" appDebounce="500" (debounceChange)="handleSearch($event)" [formControl]="searchValue" /> </div>
3. 简化 search.component.ts 逻辑
删除原有内置的debounceTime逻辑,直接使用指令返回的防抖后的值:
import { Component, OnInit, OnDestroy } from '@angular/core'; import { FormControl } from '@angular/forms'; import { TodosService } from '你的服务对应路径'; import { ChangeDetectorRef } from '@angular/core'; import { Subject } from 'rxjs'; export class TodoSearchComponent implements OnInit, OnDestroy { private ngUnsubscribe$ = new Subject<void>(); searchValue = new FormControl(); constructor(private todoService: TodosService, private changeDetectorRef: ChangeDetectorRef) {} ngOnInit(): void { // 仅保留初始化清空输入框逻辑,原有防抖逻辑全部删除 this.searchValue.setValue(''); } // 接收指令返回的防抖后搜索词直接处理 handleSearch(term: string) { this.todoService.setSearchTerm(term); this.changeDetectorRef.markForCheck(); } ngOnDestroy(): void { this.ngUnsubscribe$.next(); this.ngUnsubscribe$.complete(); } }
内容的提问来源于stack exchange,提问作者Zelars Green
相关产品推荐
相关产品推荐

