我在使用前端搜索时遇到了问题,而不是远程搜索。由于问题需要,我正在使用react.js
并创建了一个名为App
的组件。我的任务是根据类型值显示和突出匹配部分。
如果您能为我提供好的解决方案,我将不胜感激。
让我告诉您整个情景。我将这个问题分成了三个部分。
第一部分:数据的形状是什么?
数据的形状如下:
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: '/'
}
]
},
];
注意:
基本上这是我的筛选函数。
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;
};
搜索正常工作,但面临2个主要问题:
当出现上述
name
属性的匹配时,它会停止并且不会深入检查。嵌套列表name
属性也是同样的情况。当过滤发生在后台时,我们通过添加一个名为
parts
的新属性来改变原始数据,并且它是对象数组,包含突出显示的部分。但我不想改变原始数据,而是想返回包含parts
属性的新过滤数组。
请参见此处。
工作演示:
第二部分: 我使用了哪些第三方库来实现过滤和突出显示?
Lodash 字符串函数 escapeRegExp 用于转义 RegExp 特殊字符。
autosuggest-highlight 的 match 函数用于根据查询计算文本中要突出显示的字符。
之后,从同一库的parse函数帮助我们根据匹配项将给定的文本分解为
parts
。最终,它将返回一个对象数组,其中包含匹配字符串和highlight
布尔标志。因此,很容易在UI上加粗突出显示的parts
。
第三部分:应用程序组件
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;
ajax
,整个应用的前端都是用react.js
实现的。但filter
函数是主要的功能。 - Ven Nilsonlodash
函数,例如map
来返回新的修改后的数组吗? - Ven Nilson