【问题标题】:Typing in a input text is very slow using angular 4使用 angular 4 键入输入文本非常慢
【发布时间】:2020-07-17 11:21:11
【问题描述】:

当我输入文本来搜索内容时,在文本中显示一个字符非常慢。 问题是什么 ? 我用ngFor 显示了 50 个产品,如下所示,如果我显示超过 50 个产品 100 或 150 输入文本会更慢。 我应该怎么做才能解决这个问题?

<div class="width_products  products-animation " *ngFor="let product of productsService.products ; trackBy: $index"  [ngClass]="{ 'width_products_open_menu':productsService.status_menu  }" >
  <span class="each_width_product" >
    <div  class="title_products more_detail_product" (click)="set_router({ path:product['company'].company_name+'/'+product.product_title , data:product.product_id , relative:true })">
      {{product.product_title }}
      <span class="glyphicon glyphicon-chevron-down"></span><br>
      <div class=' glyphicon glyphicon-time'></div> {{product.product_date}}
    </div>
    <div class="image_product_primary " (click)="set_router({ path:product['company'].company_name+'/'+product.product_title , data:product.product_id , relative:true })">
      <img class="image_product" src="../../assets/images/products_image/{{product.product_image}}">
    </div>
    <button  (click)="product.product_in_wishList='true'; productsService.add_wish_list( product )" mat-button class="wish_list  notCloseDropdawnFavorite notCloseDropdawnCard">
      <span class="write_add_wish">{{dataservices.language.add_wishlist}}</span>
      <mat-icon *ngIf="product.product_in_wishList == 'false' " class="notCloseDropdawnFavorite notCloseDropdawnCard">favorite_border</mat-icon>
      <mat-icon  *ngIf="product.product_in_wishList == 'true' " class="hearts_div_hover notCloseDropdawnFavorite notCloseDropdawnCard">favorite</mat-icon>
    </button>
    <div class="footer_products">
      <span matTooltip="Views!">
        <div class="button_footer_products">
          <span class="glyphicon glyphicon-eye-open icon_eye"></span>
          <div class="both_write ">
            12889
          </div>
        </div>
      </span>
      <span matTooltip="Add to your card"  class="notCloseDropdawnCard notCloseDropdawnFavorite " (click)="product.product_in_cartList='true'; productsService.add_cart_list( product )">
        <div class="button_footer_products">
          <span *ngIf="product.product_in_cartList=='false'" class="glyphicon glyphicon-plus icon_eye notCloseDropdawnCard notCloseDropdawnFavorite" ></span>
          <span *ngIf="product.product_in_cartList=='true'" class="glyphicon glyphicon-ok icon_eye notCloseDropdawnCard notCloseDropdawnFavorite" ></span>
          <div class="both_write ">
            Cart
          </div>
        </div>
      </span>
      <span matTooltip="See Details!">
        <div (click)="set_router({ path:product['company'].company_name+'/'+product.product_title , data:product.product_id , relative:true })" class="button_footer_products" >
          <span class=" glyphicon glyphicon-option-horizontal icon_eye"></span>
          <div class="both_write ">
            More
          </div>
        </div>
      </span>
    </div>
    <div class="prise_products">
      Price:<del>$2500</del> $3500
    </div>
    <div class="plus_height"></div>
  </span>
</div>

在标题组件中,我有一个输入类型文本如下:

<input type="text" class="kerkim"  name="search" [(ngModel)]="typing_search" placeholder=" 
         {{dataservices.language.searchproducts}}">

【问题讨论】:

  • 所以。你能显示整个代码吗?到目前为止,有人只能猜测发生了什么。我猜您输入中的类型值用于过滤产品列表?但是现在是怎么做到的呢?
  • 直到现在我在这里分享的只是这个,我不会在服务器中发送请求来获取搜索产品,但上面的 ngFor 是显示一些产品不适用于搜索产品。问题是当我在 dom 中以慢速输入文本显示产品时,如果我没有显示任何产品,它工作得很好。

标签: javascript html angular typescript


【解决方案1】:

Debouce 效果,例如不要立即运行搜索。

class Coponent {

  private _timeoutId: number;

  //to be called on search text changed
  search(){
    clearTimeout(this._timeoutId);

    this._timeoutId = setTimeout(() => {
      //do search stuff
    }, 500) //play with delay
  }
}

使用搜索关键字缓存上一个结果。 当关键字像这样 ["k","ke","key"] 变化时,您不需要重新过滤整个数组。

class Search {

  private _keywordChanges:string[] = [];
  private _prevFilterResults: any[] = [];
  private _allData: any[] = [];


  search(keyword:string){
    let prevKeyword = this.getPrevKeyword(),
      toBeFiltered: any[];
    if(keyword.match(keyword)){ //if it was "ke" and now it is "key"
      //filter prev results only
      toBeFiltered = this._prevFilterResults;
    } else  {
      //filter prev results or even make cache for keyword
      toBeFiltered = this._allData;
    }

    let results = toBeFiltered.filter(() => {});
    this._prevFilterResults = results;
  }

  private getPrevKeyword(){
    return this._keywordChanges[this._keywordChanges.length - 1];
  }

使用 for with break 而不是 Array.filter(),在某些情况下它可能会有所帮助。例如,您已排序数组 ["a","apple","b","banana"] 和关键字“a”。

function search(array:any[], keyword:string) {
  //so
  let results = [];
  for(let i = 0; i < array.length; i++){
    let item = array[i];
    if(item.toString().startsWith(keyword)){
      results.push(item);
    } else {
      break; //as b and banana left
    }
  }
  return results;
}

看看二分搜索。 How to implement binary search in JavaScript 和哈希表Hash table runtime complexity (insert, search and delete)

【讨论】:

    【解决方案2】:

    从我的问题来看:由于数据很多,每个输入字段都很慢。所以我在重新加载数据的地方添加了“changeDetection:ChangeDetectionStrategy.OnPush”,然后一切正常。

    @Component({
      selector: 'app-app-item',
    
      templateUrl: './app-item.component.html',
    
      styleUrls: ['./app-item.component.css'],
    
      changeDetection: ChangeDetectionStrategy.OnPush,
    
    })

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-02
      • 2021-05-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多