【问题标题】:Search functionality without mutating the Original array when template is binded with Original array?模板与原始数组绑定时搜索功能而不改变原始数组?
【发布时间】:2020-04-07 12:26:42
【问题描述】:

在我的模板中,我绑定了这个snapShotArraysnapShotArray 变量正在通过 REST 端点调用填充数据。

<div class="col col-md-4 filter-by-cam">
      <input type="text" name="search" value="search" [(ngModel)]="search" #searchSnaps="ngModel"
        (keyup)="searchSnapshot(search)" />
        <button class="btn btn-primary" [disabled]="!search"
          (click)="searchSnapshot(searchSnaps.value)">Search
        </button>

    </div>

    <div *ngIf="!noData" class="game-board col-md-12">
        <div class="box camera-view-container col-md-3" *ngFor="let item of snapShotArray; let i = index; ">
          <img class="box-img camera-view" id="img{{i}}" src="{{item.image}}" crossOrigin="Anonymous">
          <div class="cam-feed">
            <span> {{item.name}}</span>
            <p>Last captured: {{item.lastCapturedDate}}</p>
          </div>
        </div>
      </div>

Component.ts:

public searchSnapshot(name: string) {
 let b = a.filter(item => item.name === name);
}

问题:

我想要的是搜索snapShotArray 数组并返回一个与用户输入的文本匹配的特定对象。一旦用户清除文本框,将 snapShotArray 替换为所有先前的对象或先前获取数据?

我知道Filter 不会改变原始数组。但是我现在卡住的地方是在将原始snapShotArray 与模板绑定时进行过滤和替换。基本上是客户端的过滤功能。我如何做到这一点?

【问题讨论】:

  • 虽然您看到许多教程和示例显示使用管道进行排序和过滤,但出于性能原因,不建议这样做angular.io/guide/pipes#appendix-no-filterpipe-or-orderbypipe。通过 RxJS 运算符或数组原型函数在组件中进行过滤不仅非常好,而且是推荐的方法。像飞行英雄管道这样的例子适用于小型数据集,但是随着应用程序的增长,这些过滤管道绝对会降低性能。
  • 您好,您能给这个问题点个赞吗?还是好的解决方案?我希望这个问题引起更多关注。主要是因为我正在使用的数据集是base64 图像。未来肯定会出现性能问题。
  • 我投了赞成票。话虽如此,请记住,您始终可以保持snapShotArray 不变,并创建一个基于snapShotArray 的附加变量filteredSnapShotArray。虽然它与您的问题不完全相同,但这是可能的方法stackoverflow.com/questions/58740256/…
  • 非常感谢,我会看看它。

标签: javascript angular typescript filter find


【解决方案1】:

始终使用管道进行过滤

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'snapshotFilter' })
export class SnapshotFilterPipe implements PipeTransform {
        transform(snapshotArr: [] , searchValue : string) {
        return snapshotArr.filter(snapshot=> {
            snapshot.name === searchValue
        });
    }
}

这里是你的 HTML

<div class="col col-md-4 filter-by-cam">
    <input type="text" name="search" value="search" [(ngModel)]="search" #searchSnaps="ngModel"
        (keyup)="searchSnapshot(search)" />
    <button class="btn btn-primary" [disabled]="!search" (click)="searchSnapshot(searchSnaps.value)">Search
    </button>

</div>

<div *ngIf="!noData" class="game-board col-md-12">
    <div class="box camera-view-container col-md-3" *ngFor="let item of snapShotArray | snapshotFilter : searchValue ; let i = index; ">
        <img class="box-img camera-view" id="img{{i}}" src="{{item.image}}" crossOrigin="Anonymous">
        <div class="cam-feed">
            <span> {{item.name}}</span>
            <p>Last captured: {{item.lastCapturedDate}}</p>
        </div>
    </div>
</div>

在你的组件中

public searchSnapshot(search: string) {
     this.searchValue = search;
}

别忘了在你的应用模块中包含管道

【讨论】:

  • 嗨.. 感谢您的解决方案.. 我也更关心它的性能方面。这会产生多大的性能影响。我使用base64 图像数据集。非常感谢对此的支持。非常希望专业人士来看看。
  • 作为一种性能,我认为它是过滤原生 Js 代码的最佳解决方案,您可以检查这些 [angular.io/guide/pipes#pure-and-impure-pipes] [blog.mgechev.com/2017/11/12/…
  • 一旦我输入一个值,整个生成的数组就会从显示中消失
【解决方案2】:

不要使用过滤器,在客户端使用管道。查看 https://angular.io/guide/pipes

<div *ngFor="let hero of (heroes | flyingHeroes)">
  {{hero.name}}
</div>

这是制作方法

import { Pipe, PipeTransform } from '@angular/core';

import { Flyer } from './heroes';

@Pipe({ name: 'flyingHeroes' })
export class FlyingHeroesPipe implements PipeTransform {
  transform(allHeroes: Flyer[]) {
    return allHeroes.filter(hero => hero.canFly);
  }
}

针对您的具体情况:

<div class="box camera-view-container col-md-3" *ngFor="let item of (snapShotArray | searchFilter: searchValue); let i = index; ">

然后在你的组件中设置搜索值。您的过滤器应该非常简单,因为它只会返回过滤后的数组,而不会将其保存在任何地方。

【讨论】:

  • 这个提议的解决方案将对性能产生什么样的影响。我在玩base64 图像数据集。
  • 不比平时多。只有当搜索参数或快照数组发生变化时,才会开始更改检测。
猜你喜欢
  • 1970-01-01
  • 2011-08-31
  • 2015-08-17
  • 1970-01-01
  • 2019-03-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多