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; // 步進為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>
等標簽來對文本做特殊展示,需要補充對于標簽元素的計算 - 多行的文本省略,不管是居中省略還是末尾省略,可能會以補充組件的形式,實現(xiàn)一個最小化的組件
寫在最后
以上就是JavaScript實現(xiàn)文本中間縮略的兩種方案的詳細內(nèi)容,更多關(guān)于JavaScript文本中間縮略的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JS繪圖Flot如何實現(xiàn)動態(tài)可刷新曲線圖
這篇文章主要介紹了JS繪圖Flot如何實現(xiàn)動態(tài)可刷新曲線圖,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-10-10showModalDialog模態(tài)對話框的使用詳解以及瀏覽器兼容
showModalDialog是jswindow對象的一個方法,和window.open一樣都是打開一個新的頁面。區(qū)別是:showModalDialog打開子窗口后,父窗口就不能獲取焦點了(也就是無法操作了)2014-01-01javascript實現(xiàn)Email郵件顯示與刪除功能
這篇文章主要介紹了javascript實現(xiàn)Email郵件顯示與刪除功能,需要的朋友可以參考下2015-11-11JavaScript實現(xiàn)QueryString獲取GET參數(shù)的方法
本文為大家詳細介紹下如何通過JavaScript實現(xiàn)QueryString獲取GET參數(shù),具體實現(xiàn)如下,感興趣的朋友可以參考下哈,希望對大家有所幫助2013-07-07JavaScript語法高亮插件highlight.js用法詳解【附highlight.js本站下載】
這篇文章主要介紹了JavaScript語法高亮庫highlight.js用法,詳細分析了highlight.js的下載、調(diào)用及具體使用技巧,需要的朋友可以參考下2016-11-11