需求:
- 该组件可以显示文本+按钮的形式,也可以显示纯文本的形式。
- 文本可以为单行或多行,为单行时超过最大宽度显示省略号,在有按钮的情况下,按钮在文本之后显示。为多行文本时,默认超过两行省略,再有按钮的情况下按钮在文本之后显示。
- 在组件中,定义自定义文本内容:如 按钮标签并将此设置为可选参数。定义文本为必传参数。定义行数并设置默认行数为2行,超过两行进行省略。
使用hooks中的useSafeState, useUpdate等
useUpdate: 返回一个函数,调用该函数会强制组件重新渲染。
useSafeState: 用法与useState 完全一样,但是在组件卸载后异步回调内的 setState 不再执行,避免因组件卸载后更新状态而导致的内存泄漏。
子组件中
1.在index.tsx文件中
interface EllipsisProp {
width?: number // 宽度 默认百分之百
text: string // 文本内容
customView?: ReactDOM //自定义文本
rows?: number // 展示几行 默认2行
}
import { useSafeState, useUpdate } from 'ahooks'
import React, { useEffect, useRef } from 'react'
const Ellipsis: React.FC<EllipsisProp> = (props) => {
// 父组件传来的值
const { width, text = '', customView, rows = 2 } = props
// 设置初始文本值
const [textView, setTextView] = useSafeState('')
const ref = useRef<HTMLDivElement>(null)
const updata = useUpdate()
useEffect(() => {
setTextView(text)
setTimeout(() => {
// 强制渲染
updata()
}, 30)
}, [text])
// 总体高度
const scrollHeight = ref.current?.scrollHeight || 0
// 可视高度
const clientHeight = ref.current?.clientHeight || 0
return (
<Div
rows={rows}
width={width ? width + 'px' : '100%'}
text={text}
isExceed={scrollHeight > clientHeight + 5} // 样式判断
>
<div className="text_view" ref={ref}>
{scrollHeight > clientHeight + 5 && (
<div className="view">{customView}</div>
)}
<span className="text">{textView}</span>
</div>
</ContentArea>
)
}
export default Ellipsis
2.在styled.ts中
import styled from 'styled-components'
const Div = styled.div<{
width: string // 宽度
rows: number // 行数
text: string // 文本
isExceed: boolean // 样式判断
}>`
display: flex;
.text_view {
width: ${(p) => p.width}; 宽度 父组件传过来的高度
line-height: 22px;
max-height: ${(p) => p.rows * 22 + 'px'}; // 最大高度 行数* 每一行的高度
overflow: hidden;
font-size: 14px;
color: #262626;
&::before {
content: '';
display: ${(p) => (!p.isExceed ? 'none' : 'inline-block')};
float: right;
width: 0px;
height: ${(p) => p.rows * 22 + 'px'};
margin-bottom: -20px;
}
.text{
whiteSpace: pre-wrap; // 保留空白符序列,但是正常地进行换行。
}
.view {
position: relative;
float: right;
clear: both;
&::before {
content: '...';
position: absolute;
left: 1px;
top: -2px;
color: #333;
transform: translateX(-100%);
}
}
.views {
clear: both;
display: inline-block;
margin-left: ${(p) => (p.text ? '6px' : 0)};
}
}
`
export { Div }
父组件调用
<Ellipsis text={'测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试'} width={319} rows={2}/>
结果:
简单的单行文本超出最大宽度显示省略 …
<span className="font_simall">
测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试
</span>
.font_simall {
max-width: 200px; 最大宽度
display: inline-block;
overflow: hidden;
white-space: nowrap; 强制不换行
text-overflow: ellipsis; 省略
}
简单的多行文本超出最大宽度显示省略 …
.font_simall {
width: 215px;
display: -webkit-box;
word-break: break-all;
text-overflow: ellipsis;
overflow: hidden;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}