【问题标题】:Angular 2 add debounce function directly to pipeAngular 2 直接向管道添加去抖动功能
【发布时间】:2017-03-13 07:16:36
【问题描述】:

我编写了一个管道,它根据给定的查询过滤出一组对象。它工作得很好,但我想做的是直接向这个管道添加一个去抖动函数,而不是如果可能的话将它添加到输入的 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;
        }
      });
    }
  }
}

关于如何在这个管道中实现它有什么想法吗?

【问题讨论】:

  • 你想在哪里应用去抖动
  • @PatrickJane 不确定它需要去哪里。
  • 为什么需要去抖?
  • @PatrickJane 所以它不会在每次击键时过滤可能包含数百个项目的列表..

标签: angular typescript debouncing angular2-pipe


【解决方案1】:

debounce 或 delay 函数是异步的,在这种情况下,您需要从管道返回一个 Promise 或一个 observable 并使用异步管道。我创建了一个简单的示例来向您展示如何使用 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}
  }
}

Plunker

【讨论】:

  • 这不只是在输入和输出之间增加延迟而不是去抖动(在处理之前等待最后一个输入之后的 x 量)吗?
  • 我们如何估计延迟值?假设我有 10 000 件物品(在我的情况下更少或更多)
  • 我刚刚测试了这个解决方案,但在我的情况下它并没有加速过滤器,我不知道如何解决这个问题。
【解决方案2】:

让我们想象一个场景,其中文本字段执行“输入即搜索”作业。为了记录有意义的搜索文本,组件应该等到输入结束。

设置管道执行延迟时间的正确方法应该如下(见代码中的cmets):

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);
  }

}

【讨论】:

    猜你喜欢
    • 2017-05-09
    • 2015-11-10
    • 2011-12-24
    • 1970-01-01
    • 1970-01-01
    • 2015-03-03
    • 2015-07-25
    • 1970-01-01
    • 2017-06-02
    相关资源
    最近更新 更多