React文本溢出组件封装以及高亮提示
Abbr 组件:使用场景:
- 当我们需要设置支持最大行数时进行省略展示
- 当我们需要设置支持设置超过多少字符进行省略展示
- 当我们需要设置支持关键字高亮展示(有点问题,当关键字被裁剪成...之后,就无法高亮)
- 当我们需要支持忽略大小写高亮
- 当我们需要支持ToolTip展示全部文本,且可以在toolTip上进行关键字高亮
Abbr 组件tsx
import { Tooltip } from "antd";
import React from "react";
import "./index.less";
import { finxAllIndex, returnRenderName } from "./tools";
interface AbbrTextProps {
/* 需要展示的文本 */
text: string;
/* 截取的长度 */
length?: number;
/* 设置行数 */
line?: number;
/* 设置样式 */
className?: string;
/* 高亮关键字 */
keyWord?: string;
/* 是否在tooltip中也高亮展示 默认不展示 */
showTooltipHighlight?: boolean;
/* 主题 */
theme?: "default" | "warning" | "error" | "success";
/* 是否忽略大小写 */
ignoreCase?: boolean;
}
const AbbrText: React.FC<AbbrTextProps> = ({
text,
length,
line,
className,
keyWord = "",
showTooltipHighlight = false,
theme = "default",
ignoreCase = false,
}) => {
let displayText: JSX.Element | string = text;
let style = {};
let showTooltip = false;
/* 如果有高亮的关键字 */
const heightKeyWord = (
readyText: string,
keyWord: string,
showAll?: boolean
): JSX.Element => {
/* 目标结果在字符串中的所有索引 */
const findAllIndex = finxAllIndex(readyText, keyWord, ignoreCase);
/* 高亮之后标签 */
const renderName = returnRenderName(readyText, keyWord, findAllIndex, {
theme,
});
const renderText = (
<>
{renderName}
{!showAll && length && text.length > length && <span>...</span>}
</>
);
return renderText;
};
if (length && text.length > length) {
displayText = text.substring(0, length);
showTooltip = true;
} else if (line) {
style = {
display: "-webkit-box",
"-webkit-box-orient": "vertical",
overflow: "hidden",
textOverflow: "ellipsis",
};
}
displayText = heightKeyWord(displayText, keyWord);
/* length 优先级大于line ,同时设置length 生效 */
if (length && line) {
console.warn("Abbr组件警告⚠️:length 和 line 同时设置时,length 优先级高");
}
// 当文本被截短或者设置了行数限制时显示提示
const content = (
<span
className={`abbrtext ${className}`}
style={{ ...style, WebkitLineClamp: line, lineClamp: line }}
>
{displayText}
</span>
);
return (
<Tooltip
title={
(showTooltip || line) && showTooltipHighlight
? heightKeyWord(text, keyWord, true)
: text
}
>
{content}
</Tooltip>
);
};
AbbrText.defaultProps = {
length: undefined,
line: 1,
className: "",
};
export default AbbrText;
Abbr 组件less
.abbrtext {
word-break: break-all;
width: fit-content;
}
.hightlight {
&.default {
color: blue;
}
&.success {
color: green;
}
&.error {
color: red;
}
&.warning {
color: orange;
}
}
Abbr 组件工具函数
/**
* @param str 字符串
* @param itemStr 目标字符串
* @param ignoreCase 是否忽略大小写
* @returns 目标结果在字符串中的所有索引
*/
export const finxAllIndex = (
str: string,
itemStr: string,
ignoreCase = false
) => {
// 初始化结果数组
const result = [];
// 遍历字符串,寻找目标项并记录索引
for (let i = 0; i <= str.length - itemStr.length; ) {
let index = str.indexOf(itemStr, i);
if (ignoreCase) {
index = str.toLocaleLowerCase().indexOf(itemStr.toLocaleLowerCase(), i);
}
if (index !== -1) {
// 更简洁的判断条件
result.push(index);
i = index + itemStr.length; // 更新i值
} else {
i++;
}
}
return result;
};
/**
* @param str 字符串
* @param keyWords 关键字
* @param allIndexArray 所有索引
* @param config 配置
* @param config.theme 主题
* @returns 高亮之后标签
*/
export const returnRenderName = (
str: string,
keyWords: string,
allIndexArray: Array<number>,
config?: {
theme?: "default" | "warning" | "error" | "success";
}
) => {
const { theme = "default" } = config || {};
if (allIndexArray.length === 0) {
return str;
}
/* 最终结果 */
let res: string | JSX.Element | null = null;
let loopindex = 0;
const loop = (index = 0): string | JSX.Element => {
res = (
<>
{res}
{str.substring(index, allIndexArray[loopindex])}
<span className={`hightlight ${theme}`}>
{str.substring(allIndexArray[loopindex], keyWords.length)}
</span>
</>
);
loopindex++;
if (allIndexArray.length <= loopindex) {
res = (
<>
{res}
{str.substring(allIndexArray[loopindex - 1] + keyWords.length)}
</>
);
return res;
} else {
return loop(allIndexArray[loopindex - 1] + keyWords.length);
}
};
loop();
return res;
};
Abbr 组件测试
import React from "react";
import AbbrText from "./components/Abbr";
function App() {
return (
<>
<AbbrText
text="Hello World"
keyWord="hello"
length={10}
showTooltipHighlight
ignoreCase
theme="warning"
/>
</>
);
}
export default App;