Angular 2 直接给管道添加去抖功能
Angular 2 add debounce function directly to pipe
我写了一个管道,它根据给定的查询过滤出一组对象。它工作得很好,但我想做的是直接向该管道添加一个去抖功能,而不是将其添加到输入的 keyup 事件中,如果可能的话。
我一直在四处寻找解决方案,但似乎找不到任何与我正在寻找的内容相关的内容。
import {Pipe, PipeTransform} from '@angular/core';
@Pipe({
name: 'filterBy'
})
export class FilterByPipe implements PipeTransform {
transform(value: any, args: string[]): any[] {
if (!args[0]) {
return value;
}
else if (value) {
return value.filter(item => {
// TODO: Allow args[1] to be null, therefore searching in all object properties
if ((typeof item[args[1]] === 'string' || item[args[1]] instanceof String) && (item[args[1]].toLowerCase().indexOf(args[0].toLowerCase()) !== -1)) {
return true;
}
});
}
}
}
关于如何在此管道中实现它的任何想法?
去抖动或延迟函数是异步的,在这种情况下,您需要 return 来自管道的承诺或可观察对象并使用异步管道。我创建了一个简单的示例来向您展示如何使用 observable 做到这一点。
@Pipe({
name: 'myfilter'
})
export class MyFilterPipe implements PipeTransform {
transform(items, filterBy) {
const filteredItems = items.filter(item => item.title.indexOf(filterBy.title) !== -1);
return Observable.of(filteredItems).delay(1000);
}
}
@Component({
selector: 'my-app',
template: `
<div>
<ul>
<li *ngFor="let item of items | myfilter:filterBy | async">
{{item.title}}
</li>
</ul>
<input type="text" (input)="filter($event)">
</div>
`,
})
export class App {
filterBy;
constructor() {
this.filterBy = {title: 'hello world'};
this.items = [{title: 'hello world'}, {title: 'hello kitty'}, {title: 'foo bar'}];
}
filter($event) {
this.filterBy = {title: $event.target.value}
}
}
让我们想象一个文本字段执行 'search-as-you-type' 工作的场景。为了记录有意义的搜索文本,组件应该等到键入结束。
设置管道执行延迟时间的正确方法应该如下(见代码中的注释):
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'searchFilter'
})
export class SearchFilterPipe implements PipeTransform {
//-----
// 1
// ----
//hold a timeout handle on class scope
private timeoutHandle: number = -1;
constructor(private dbLogger: DbLogService) {
}
transform(items: any, value?: any): any {
if (!items) return [];
//-----
// 2
// ----
//clear time out handle on every pipe call
//so that only handles created earlier than
// 1000ms would execute
window.clearTimeout(this.timeoutHandle);
//-----
// 3
// ----
//create time out handle on every pipe call
this.timeoutHandle = window.setTimeout(() => {
//-----
// 4
// ----
//if there is no further typing,
//then this timeout handle made the way to here:
console.log("search triggered with value: " + value);
}, 1000);
return items.filter(it => it["name"].toLowerCase().indexOf(value.trim().toLowerCase()) !== -1);
}
}
我写了一个管道,它根据给定的查询过滤出一组对象。它工作得很好,但我想做的是直接向该管道添加一个去抖功能,而不是将其添加到输入的 keyup 事件中,如果可能的话。
我一直在四处寻找解决方案,但似乎找不到任何与我正在寻找的内容相关的内容。
import {Pipe, PipeTransform} from '@angular/core';
@Pipe({
name: 'filterBy'
})
export class FilterByPipe implements PipeTransform {
transform(value: any, args: string[]): any[] {
if (!args[0]) {
return value;
}
else if (value) {
return value.filter(item => {
// TODO: Allow args[1] to be null, therefore searching in all object properties
if ((typeof item[args[1]] === 'string' || item[args[1]] instanceof String) && (item[args[1]].toLowerCase().indexOf(args[0].toLowerCase()) !== -1)) {
return true;
}
});
}
}
}
关于如何在此管道中实现它的任何想法?
去抖动或延迟函数是异步的,在这种情况下,您需要 return 来自管道的承诺或可观察对象并使用异步管道。我创建了一个简单的示例来向您展示如何使用 observable 做到这一点。
@Pipe({
name: 'myfilter'
})
export class MyFilterPipe implements PipeTransform {
transform(items, filterBy) {
const filteredItems = items.filter(item => item.title.indexOf(filterBy.title) !== -1);
return Observable.of(filteredItems).delay(1000);
}
}
@Component({
selector: 'my-app',
template: `
<div>
<ul>
<li *ngFor="let item of items | myfilter:filterBy | async">
{{item.title}}
</li>
</ul>
<input type="text" (input)="filter($event)">
</div>
`,
})
export class App {
filterBy;
constructor() {
this.filterBy = {title: 'hello world'};
this.items = [{title: 'hello world'}, {title: 'hello kitty'}, {title: 'foo bar'}];
}
filter($event) {
this.filterBy = {title: $event.target.value}
}
}
让我们想象一个文本字段执行 'search-as-you-type' 工作的场景。为了记录有意义的搜索文本,组件应该等到键入结束。
设置管道执行延迟时间的正确方法应该如下(见代码中的注释):
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'searchFilter'
})
export class SearchFilterPipe implements PipeTransform {
//-----
// 1
// ----
//hold a timeout handle on class scope
private timeoutHandle: number = -1;
constructor(private dbLogger: DbLogService) {
}
transform(items: any, value?: any): any {
if (!items) return [];
//-----
// 2
// ----
//clear time out handle on every pipe call
//so that only handles created earlier than
// 1000ms would execute
window.clearTimeout(this.timeoutHandle);
//-----
// 3
// ----
//create time out handle on every pipe call
this.timeoutHandle = window.setTimeout(() => {
//-----
// 4
// ----
//if there is no further typing,
//then this timeout handle made the way to here:
console.log("search triggered with value: " + value);
}, 1000);
return items.filter(it => it["name"].toLowerCase().indexOf(value.trim().toLowerCase()) !== -1);
}
}