JavaScript實現(xiàn)文本中間縮略的兩種方案
前言
項目中經(jīng)常會遇到縮略展示文字的場景,即要求文字在一行不換行展示,超出自動展示...
常用的展示效果有兩種,文字中間縮略以及文字末尾縮略,效果如下所示
// 中間縮略 這是一段超長...超長文字如何展示 // 末尾縮略 這是一段超長的文字,看看超長....
對于描述之類的文本,一般選擇末尾縮略,這種場景僅靠css即可快速實現(xiàn)。但是對于文件名之類的場景,會期望中間縮略,保留末尾的文件后綴。下面分別介紹下兩種方案的實現(xiàn)。
末尾縮略
使用css需實現(xiàn)3個效果:
- 內(nèi)容超出不展示
- 文字不會自動折行
- 設(shè)置對應(yīng)超出樣式
如果在實現(xiàn)過程中發(fā)現(xiàn)樣式不生效,一定是上述3個條件有不滿足的。
對應(yīng)css代碼如下:
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
中間縮略
中間縮略的樣式,只能手動切分字符串,并在中間拼接..., 因此關(guān)鍵在與,如何獲得要切分的起止位置。
思路整理
本例使用
React實現(xiàn)。之所以只用js實現(xiàn),一個是因為簡單,第二個則是使用css的大部分方式,需要重疊兩個div,用戶在選中的時候,體驗不太好。
- 因為要做到通用性所以,
container的寬度是不能確定的,它的寬度需要根據(jù)它外層的父元素來決定。因此定義兩層嵌套元素,外層寬度跟隨父元素,并設(shè)置overflow: hidden;white-space: nowrap;。內(nèi)層寬度不做限定,保證可以正常占位。
<div className="auto-ellipsis-text">
<span className="auto-ellipsis-text-inner">{str}</span>
</div>
.auto-ellipsis-text{
width: 100%;
overflow: hidden;
white-space: nowrap;
}
- 然后實現(xiàn)下寬度計算邏輯,并更新渲染節(jié)點
在div.auto-ellipsis-text上增加ref,獲取對應(yīng)的dom句柄
const handle = useCallback(() => {
// 獲取渲染節(jié)點的句柄
const cu = textRef.current;
if (!cu) {
return;
}
// 獲取此時父元素寬度
const width = cu.clientWidth;
// 獲取文本節(jié)點寬度
const textChild = cu.firstElementChild as HTMLElement;
const innerWidth = textChild.offsetWidth;
// 沒有超出則不處理
if (width >= innerWidth) {
return;
}
// 計算切分位置
const splitWidth = width / 2;
const range = document.createRange();
const length = textChild.innerText.length;
const arr = [];
let countWidth = 0;
let startIndex = 0;
let endIndex = 0;
// 步進(jìn)為2,逐個獲取對應(yīng)的寬度,并在首次累計寬度大于 splitWidth 時記錄起始位置,
// 在首次剩余寬度小于 splitWidth 時,記錄截止位置,停止for循環(huán)
for (let i = 0; i < length - 2; i += 2) {
range.setStart(textChild.childNodes[0], i);
range.setEnd(textChild.childNodes[0], i + 2);
const rs = range.getBoundingClientRect();
arr.push({ index: i, width: rs.width });
countWidth += rs.width;
if (countWidth > splitWidth && !startIndex) {
startIndex = i;
}
if (innerWidth - countWidth < splitWidth) {
endIndex = i + 2;
break;
}
}
// 切分字符串并補充縮略符
const newStr = text.slice(0, startIndex) + '...' + str.slice(endIndex);
// 更新渲染節(jié)點
setStr(newStr);
}, []);
最終實現(xiàn)
- 如果每個實例都監(jiān)聽父元素寬度的變化,性能太差,因此補充入?yún)?code>version,由調(diào)用方自行監(jiān)聽寬度并變更
version來觸發(fā)更新 - 在
useEffect中監(jiān)聽version和text的變化,先重置str,保證渲染是最新的,然后在下個事件循環(huán)中,使用上文中的方式,計算切分位置并更新文本渲染 - 不直接依賴
str是為了防止計算出問題導(dǎo)致的無限死循環(huán),上條中useEffect只會在text變化或者version變化后才會執(zhí)行
export default function AutoEllipsisText({
text,
className,
version,
}: {
text: string;
className?: string;
version?: number;
}) {
const [str, setStr] = useState(text);
const textRef = useRef<HTMLDivElement>(null);
const handle = useCallback(() => {
/* 功能函數(shù)...*/
}, []);
useEffect(() => {
setStr(text);
Promise.resolve().then(() => {
handle();
});
}, [text, version]);
return (
<div className={`auto-ellipsis-text ${className || ''}`} ref={textRef}>
<span className="auto-ellipsis-text-inner">{str}</span>
</div>
);
}
使用
- 上述示例對應(yīng)代碼倉庫為auto-ellipsis-text,
Demo放置在這里,也可以clone倉庫后直接本地運行。
調(diào)用示例
<AutoEllipsisText text="這是一個超長的文件名超長的文件名超長的文件名文件末尾在這里.txt" version={width} />

- 對應(yīng)NPM包也已經(jīng)發(fā)布,有需要可以去下載
待優(yōu)化項
- 很多時候可能需要使用
<em>等標(biāo)簽來對文本做特殊展示,需要補充對于標(biāo)簽元素的計算 - 多行的文本省略,不管是居中省略還是末尾省略,可能會以補充組件的形式,實現(xiàn)一個最小化的組件
寫在最后
以上就是JavaScript實現(xiàn)文本中間縮略的兩種方案的詳細(xì)內(nèi)容,更多關(guān)于JavaScript文本中間縮略的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript如何動態(tài)創(chuàng)建table表格
這篇文章主要介紹了JavaScript如何動態(tài)創(chuàng)建table表格,一些時候需要動態(tài)的創(chuàng)建和刪除表格,接下來的文章中將為大家介紹下javascript是如何做到的,感興趣的朋友不要錯過2015-11-11
Electron實現(xiàn)自定義全量更新的詳細(xì)教程
本文主要介紹如何手動實現(xiàn)客戶端應(yīng)用的自動全量更新,通過改造electron-updater實現(xiàn)版本,系統(tǒng)等字段的動態(tài)判斷更新,實現(xiàn)后臺配置不同設(shè)備,版本,系統(tǒng)的版本更新,可自行在后臺配置定向更新,批量更新等,需要的朋友可以參考下2025-08-08
Layui數(shù)據(jù)表格之獲取表格中所有的數(shù)據(jù)方法
今天小編就為大家分享一篇Layui數(shù)據(jù)表格之獲取表格中所有的數(shù)據(jù)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08
jQuery 表單驗證插件formValidation實現(xiàn)個性化錯誤提示
這里介紹另外一個表單驗證插件formValidation,這個插件與前面兩個插件的最大區(qū)別在于它實現(xiàn)了個性化的錯誤提示信息,顯示在表單元素右上角類似于提示條2009-06-06

