javascript数组过滤器在REACT中非常慢

时间:2019-02-26 12:51:27

标签: javascript reactjs

我有一个自定义列表框,一个div,其中包含其他div个子级的垂直列表。我有input可以搜索列表中的其他内容。它正在工作,但是在大数据中,它的运行速度非常慢。

搜索条件也随列选择器动态产生。如何提高搜索性能。

正确地,准备过滤数据以进行搜索并保持页面加载状态

prepareFilterData(allData) {
  const filteredData = [];
  let columnChooser = JSON.parse(getItemFromLocalStorage("ColumnData"));
  allData.map(item => {
    var data = "";
    columnChooser.map(element => {
      var newData = { value: item[element.value], format: element.format };
      var filterItem = getFilterDataFormat(newData);
      data += filterItem + " ";
    });
    filteredData.push(data);
  });
  this.setState({
    filteredData: filteredData
  });
}

第二,当用户在textbox中输入一个字符时,我正在检查filteredData

filterList() {
  const updatedList = this.state.allData.length > 0 ? this.state.allData : [];
  var filteredData = [];
  filteredData = updatedList.filter((item, index) => {
    const data = this.state.filteredData[index];
    return data.indexOf(this.state.searchInputValue) !== -1;
  });
  return filteredData;
}

这是input声明

<input 
  id="searchBox"
  type="text"
  className="filter-input empty"
  placeholder="Search"
  onChange={this.filterList}
  value={this.props.state.searchInputValue}
  style={{ width: "100%" }} />

2 个答案:

答案 0 :(得分:0)

使用标准的for循环可以显着提高性能,尤其是在您使用indexOf的情况下,这会导致filter中的另一个迭代。过滤操作使用回调,并且由于语法更简单而经常使用,但是正是这些回调使操作变慢,尤其是在大数据上。

了解更多here

答案 1 :(得分:0)

我找到了解决方法。

解决方案:

我在项目中创建了一个util.js,然后我叫createFilter function

import Fuse from "fuse.js";
import { toTrLowerCase } from "./process";

function flatten(array) {
  return array.reduce((flat, toFlatten) => flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten), []);
}

export function getValuesForKey(key, item) {
  const keys = key.split(".");
  let results = [item];
  keys.forEach(_key => {
    const tmp = [];
    results.forEach(result => {
      if (result) {
        if (result instanceof Array) {
          const index = parseInt(_key, 10);
          if (!isNaN(index)) {
            return tmp.push(result[index]);
          }
          result.forEach(res => {
            tmp.push(res[_key]);
          });
        } else if (result && typeof result.get === "function") {
          tmp.push(result.get(_key));
        } else {
          tmp.push(result[_key]);
        }
      }
    });

    results = tmp;
  });

  // Support arrays and Immutable lists.
  results = results.map(r => (r && r.push && r.toArray ? r.toArray() : r));
  results = flatten(results);

  return results.filter(r => typeof r === "string" || typeof r === "number");
}

export function searchStrings(strings, term, { caseSensitive, fuzzy, sortResults, exactMatch } = {}) {
  strings = strings.map(e => e.toString());

  try {
    if (fuzzy) {
      if (typeof strings.toJS === "function") {
        strings = strings.toJS();
      }
      const fuse = new Fuse(
        strings.map(s => {
          return { id: s };
        }),
        { keys: ["id"], id: "id", caseSensitive, shouldSort: sortResults }
      );
      return fuse.search(term).length;
    }
    return strings.some(value => {
      try {
        if (!caseSensitive) {
          value = value.toLowerCase();
        }
        if (exactMatch) {
          term = new RegExp("^" + term + "$", "i");
        }
        if (value && value.search(term) !== -1) {
          return true;
        }
        return false;
      } catch (e) {
        return false;
      }
    });
  } catch (e) {
    return false;
  }
}

export function createFilter(term, keys, options = { caseSensitive: false, fuzzy: false, sortResults: false, exactMatch: false }) {
  debugger;
  return item => {
    if (term === "") {
      return true;
    }

    if (!options.caseSensitive) {
      term = term.toLowerCase();
    }

    const terms = term.split(" ");

    if (!keys) {
      return terms.every(term => searchStrings([item], term, options));
    }

    if (typeof keys === "string") {
      keys = [keys];
    }

    return terms.every(term => {
      // allow search in specific fields with the syntax `field:search`
      let currentKeys;
      if (term.indexOf(":") !== -1) {
        const searchedField = term.split(":")[0];
        term = term.split(":")[1];
        currentKeys = keys.filter(key => key.toLowerCase().indexOf(searchedField) > -1);
      } else {
        currentKeys = keys;
      }

      return currentKeys.some(key => {
        const values = getValuesForKey(key, item);
        values[0] = toTrLowerCase(values[0]);
        return searchStrings(values, term, options);
      });
    });
  };
}

然后我将fuse.js添加到了package.json

"fuse.js": "^3.0.0"

我这样调用createFilter函数... term正在搜索value key

keysToFilter是您要搜索的array column

this.state.allData.filter(createFilter(term, this.state.keysToFilter));

链接:https://github.com/enkidevs/react-search-input

相关问题