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

- 對(duì)應(yīng)NPM包也已經(jīng)發(fā)布,有需要可以去下載
待優(yōu)化項(xiàng)
- 很多時(shí)候可能需要使用
<em>等標(biāo)簽來(lái)對(duì)文本做特殊展示,需要補(bǔ)充對(duì)于標(biāo)簽元素的計(jì)算 - 多行的文本省略,不管是居中省略還是末尾省略,可能會(huì)以補(bǔ)充組件的形式,實(shí)現(xiàn)一個(gè)最小化的組件
寫在最后
以上就是JavaScript實(shí)現(xiàn)文本中間縮略的兩種方案的詳細(xì)內(nèi)容,更多關(guān)于JavaScript文本中間縮略的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript實(shí)現(xiàn)簡(jiǎn)單計(jì)時(shí)器
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)簡(jiǎn)單計(jì)時(shí)器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06
JS繪圖Flot如何實(shí)現(xiàn)動(dòng)態(tài)可刷新曲線圖
這篇文章主要介紹了JS繪圖Flot如何實(shí)現(xiàn)動(dòng)態(tài)可刷新曲線圖,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10
showModalDialog模態(tài)對(duì)話框的使用詳解以及瀏覽器兼容
showModalDialog是jswindow對(duì)象的一個(gè)方法,和window.open一樣都是打開一個(gè)新的頁(yè)面。區(qū)別是:showModalDialog打開子窗口后,父窗口就不能獲取焦點(diǎn)了(也就是無(wú)法操作了)2014-01-01
javascript實(shí)現(xiàn)Email郵件顯示與刪除功能
這篇文章主要介紹了javascript實(shí)現(xiàn)Email郵件顯示與刪除功能,需要的朋友可以參考下2015-11-11
JavaScript實(shí)現(xiàn)QueryString獲取GET參數(shù)的方法
本文為大家詳細(xì)介紹下如何通過(guò)JavaScript實(shí)現(xiàn)QueryString獲取GET參數(shù),具體實(shí)現(xiàn)如下,感興趣的朋友可以參考下哈,希望對(duì)大家有所幫助2013-07-07
js實(shí)現(xiàn)WebSocket 連接的示例代碼
本文主要介紹了js實(shí)現(xiàn)WebSocket 連接的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-05-05
JavaScript語(yǔ)法高亮插件highlight.js用法詳解【附highlight.js本站下載】
這篇文章主要介紹了JavaScript語(yǔ)法高亮庫(kù)highlight.js用法,詳細(xì)分析了highlight.js的下載、調(diào)用及具體使用技巧,需要的朋友可以參考下2016-11-11

