我有一个自定义列表框,一个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%" }} />
答案 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));