我想显示子字符串的高亮显示。目前,JSX解决了以下问题:
这是产生这个字符串的算法;也许你可以看到我的策略并告诉我它是否是一个愚蠢的:
/**
* prepares string with JSX span tags to assist with highlighting of search result matches
* @param {string} string to find the match within
* @param {string} matchString the search query string that we are highlighting against
*
* @returns {Array} an array containing characters and JSX for syntax highlighting
*/
export const matchHighlighting = (name, matchString) => {
let renderArray = []
let buffer = []
let nameArray = name.split("")
let matchIdx = 0;
for (var i = 0; i < nameArray.length; i++) {
if (matchString[0] == nameArray[i]) {
let matching = true;
matchIdx = 0;
/* start testing for match, if successfully get through match, place inside tag
and push that to the render array */
while (matching) {
if (matchString[matchIdx] == nameArray[i]) {
buffer.push(nameArray[i]);
if (matchIdx + 1 == matchString.length) {
/* complete match add JSX */
renderArray.push(<span className="search-match-string">
{ buffer }
</span>);
matching = false;
buffer = [];
break;
}
i++
matchIdx++
} else {
/* no longer match, clean up matching state
and return to normal iteration */
matching = false;
buffer.push(nameArray[i]);
renderArray = renderArray.concat(buffer);
}
}
} else { /* no match, all is chill */
renderArray.push(nameArray[i]);
}
}
return renderArray
}
我正在努力寻找解决这个策略产生的关键错误的方法:
Each child in an array or iterator should have a unique "key" prop
我如何以标签不会包含在字符串中的方式“加入”这些字符数组和span标签?
要么
如何为构成此数组的单个字符和jsx标记分配键?
这些至少是我想弄清楚的两个解决方案,并没有在它上面做出很好的理由。我想我将继续尝试解决第一个策略(即没有一个字符数组但只有一个字符串)但我对如何包含JSX标记感到迷茫......
因此,我认为利用indexOf
进行匹配会更容易,并构建匹配/非匹配数组。然后将此数组转换为适当的<span>
s。例如:
function buildPieces(str, match) {
var pieces = []
var index, pos = 0
while ((index = str.indexOf(match, pos)) >= 0) {
if (pos !== index) {
pieces.push(str.substr(pos, index - pos))
}
pieces.push(match)
pos = index + match.length
}
if (pos < str.length) {
pieces.push(str.substr(pos));
}
return pieces;
}
const str = 'This is a test string with test in it twice.'
const matchStr = 'test'
const pieces = buildPieces(str, matchStr)
然后在你的组件内
<span>{pieces.map(item => {
if(item === matchStr){
return <span className="match">{item}</span>
}else{
return item
}
})}</span>
你可以看到一个演示here