[英]React.js search filtration on the array of objects
我遇到了search
問題。 它是前端搜索而不是遠程搜索,我使用react.js
因為它是問題中的一個要求,並創建了一個名為App
的組件。 我的任務是根據類型值顯示和突出顯示匹配的部分。
我會很感激的。 如果您為此提供了一個很好的解決方案。
讓我告訴你整個場景。 我將這個問題分為 3 個部分。
第 1 部分:數據的形狀是什么?
數據的形狀是這樣的:
src/data.js:
export default [
{
id: 1,
name: 'Wordpress',
list: [
{
id: 1,
name: 'Best Mobile App Builder',
slug: '/'
},
{
id: 2,
name: 'Best Wordpress Themes',
slug: '/'
},
{
id: 3,
name: 'Best Website Creator',
slug: '/'
},
{
id: 4,
name: 'Best Wordpress Builder',
slug: '/'
}
]
},
{
id: 2,
name: 'SaaS',
list: [
{
id: 1,
name: 'Appointment Scheduling Software',
slug: '/'
},
{
id: 2,
name: 'Design Services',
slug: '/'
},
{
id: 3,
name: 'Online Cloud Storage',
slug: '/'
},
{
id: 4,
name: 'Remote PC Access',
slug: '/'
}
]
},
];
注意:
基本上這是我的過濾器 function。
src/filter.js:
import _ from 'lodash';
import match from 'autosuggest-highlight/match';
import parse from 'autosuggest-highlight/parse';
/**
* Returns the new filtered array with highlighted parts.
* @param data {Array<Object>} - The collection to iterate over.
* @param inputValue {string} - The input value.
* @return {Array} - Returns the new filtered array.
*/
export const filterByNames = (data, inputValue) => {
// Create a dynamic regex expression object with ignore case sensitivity
const re = new RegExp(_.escapeRegExp(inputValue), 'i');
const results = data.filter((object) => {
if (re.test(object.name)) {
return true;
} else {
return object.list.some((item) => {
if (re.test(item.name)) {
// Calculates the characters to highlight in text based on query
const matches = match(item.name, inputValue);
// Breaks the given text to parts based on matches.
// After that create a new property named `parts` and assign an array to it.
item['parts'] = parse(item.name, matches);
return true;
} else {
return false;
}
});
}
});
return results;
};
搜索工作正常,但面臨兩個主要問題。
當name
屬性發生上述匹配時,它會停止並且不會更深入地進行 go。 嵌套列表name
屬性也發生了同樣的事情。
當過濾發生在幕后時,我們通過添加一個名為parts
的新屬性來改變原始數據,該屬性包含突出顯示的部分,它是一個對象數組。 但我不想改變原始數據,而是想返回包含parts
屬性的新過濾數組。
看到這個。
工作演示:
第 2 部分:我使用哪些第三方庫進行過濾和突出顯示?
lodash字符串 function escapeRegExp用於轉義 RegExp 特殊字符。
autosuggest-highlight匹配function 以根據查詢計算要在文本中突出顯示的字符。
之后,從同一個庫中解析function 幫助我們根據匹配將給定文本分解為parts
。 最后,它將返回一個帶有匹配字符串的對象數組並highlight
boolean 標志。 所以我們很容易在 UI 上將突出顯示的parts
加粗。
第 3 部分:應用程序組件
import React, { useState } from 'react';
import { filterByNames } from './filter';
import data from './data';
/**
* Return the JSX for the List
* @param data {Array<Object>} - The collection to iterate over.
* @return {null|*} - Returns the JSX or null.
*/
const renderList = (data) => {
if (Array.isArray(data) && data.length > 0) {
return data.map((object) => {
return (
<div key={object.id}>
<h1>{object.name}</h1>
<ul className="list">
{object.list.map((item) => {
return (
<li key={item.id}>
{item.parts ? (
<a href={item.slug}>
{item.parts.map((part, index) => (
<span
key={index}
style={{ fontWeight: part.highlight ? 700 : 400 }}
>
{part.text}
</span>
))}
</a>
) : (
<a href={item.slug}>{item.name}</a>
)}
</li>
)
})}
</ul>
</div>
)
})
} else {
return null
}
};
// Main App Component
const App = () => {
const [value, setValue] = useState('');
const onChangeHandler = (event) => {
const { target } = event;
const val = target.value;
setValue(val);
};
const results = !value ? data : filterByNames(data, value);
return (
<div className="demo">
<input type="text" value={value} onChange={onChangeHandler}/>
<div className="demo-result">
{ renderList(results) }
</div>
</div>
);
};
export default App;
這是修改后的代碼。
export const filterByNames = (data, inputValue) => {
// Create a dynamic regex expression object with ignore case sensitivity
const re = new RegExp(_.escapeRegExp(inputValue), "i");
const clonedData = _.cloneDeep(data);
const results = clonedData.filter((object) => {
return object.list.filter((item) => {
if (re.test(item.name)) {
// Calculates the characters to highlight in text based on query
const matches = match(item.name, inputValue);
// Breaks the given text to parts based on matches.
// After that create a new property named `parts` and assign an array to it.
item["parts"] = parse(item.name, matches);
return true;
} else {
return false;
}
}).length > 0 || re.test(object.name);
});
return results;
};
分叉鏈接在這里。 https://codesandbox.io/s/search-frontend-forked-e3z55
這是解決了這兩個問題的代碼
export const filterByNames = (data, inputValue) => {
// Create a dynamic regex expression object with ignore case sensitivity
const re = new RegExp(_.escapeRegExp(inputValue), "i");
// since we cannot directly mutate the data object, why not copy it here ? (or if the data is bigger and copying is also not an option then consider using two arrays of data, one for the mutation and one default maybe)
let data_ = JSON.parse(JSON.stringify(data));
// filter and return the newer copy of the object.
const results = data_.filter((object) => {
// since we need the highlighting in both cases, on top level, or even in nested level so create separate function for that.
let highLightEm = (list) => {
return object.list.some((item) => {
if (re.test(item.name)) {
// Calculates the characters to highlight in text based on query
const matches = match(item.name, inputValue);
// Breaks the given text to parts based on matches.
// After that create a new property named `parts` and assign an array to it.
item["parts"] = parse(item.name, matches);
return true;
} else {
return false;
}
});
};
if (re.test(object.name)) {
// check for the highlighting in the inner name
highLightEm(object);
return true;
} else {
return highLightEm(object);
}
});
return results;
};
https://codesandbox.io/s/search-frontend-forked-kxui9?file=/src/filter.js
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.