多行省略的完整原理)
react-lines-ellipsis源碼深度剖析隱藏Canvas測量法實現(xiàn)多行省略的完整原理【免費下載鏈接】react-lines-ellipsisSimple multiline ellipsis component for React.JS項目地址: https://gitcode.com/gh_mirrors/re/react-lines-ellipsisreact-lines-ellipsis是 React 生態(tài)中最經(jīng)典的多行省略組件之一。當 CSS 的-webkit-line-clamp在非 WebKit 瀏覽器上失效時它通過一套被稱為隱藏 Canvas 測量法的巧妙機制在任意現(xiàn)代瀏覽器上都能精確實現(xiàn)多行文本省略。本文將從源碼剖析角度逐行拆解這套隱藏 Canvas 測量法實現(xiàn)多行省略的完整原理讓新手也能看懂這個號稱 Poor mans multiline ellipsis 的組件到底聰明在哪里。 核心關(guān)鍵詞react-lines-ellipsis、多行省略、Canvas測量法、源碼剖析、React 多行文本截斷為什么多行省略一直是前端難題單行省略一行 CSS 就能搞定text-overflow: ellipsis。但多行省略multiline ellipsis至今沒有 W3C 標準方案最常見的-webkit-line-clamp只對 WebKit/Blink 內(nèi)核有效Firefox 長期不支持。于是社區(qū)涌現(xiàn)出兩類方案方案類型代表優(yōu)點缺點純 CSS 方案-webkit-line-clamp性能好、實現(xiàn)簡單兼容性差、不可控省略號樣式JS 測量方案react-lines-ellipsis跨瀏覽器、精確控制需要 DOM 測量、有性能開銷react-lines-ellipsis 選擇了后者而它的測量核心就是一個看不見的影子 DOM。認識 react-lines-ellipsis 的核心架構(gòu)整個項目非常精簡核心源碼集中在src/目錄下共 6 個文件src/index.jsx主組件 LinesEllipsis處理純文本省略src/common.js隱藏 Canvas 的樣式清單與基礎(chǔ)配置src/html.jsxHTMLEllipsis支持富文本 HTML 省略src/loose.jsx基于 WebkitLineClamp 的輕量版本src/responsiveHOC.jsx響應(yīng)式高階組件監(jiān)聽窗口變化src/helpers.js工具函數(shù)其中index.jsx的 186 行代碼就是隱藏 Canvas 測量法的完整實現(xiàn)。隱藏 Canvas 測量法的完整工作原理整套算法可以拆成五個步驟環(huán)環(huán)相扣第一步克隆一個影子節(jié)點影子 Canvas組件掛載后initCanvas()會在document.body末尾追加一個絕對定位、高度為 0、overflow hidden 的隱藏 div類名是LinesEllipsis-canvas。關(guān)鍵在copyStyleToCanvas()const targetStyle window.getComputedStyle(this.target) mirrorProps.forEach((key) { this.canvas.style[key] targetStyle[key] })src/common.js中的mirrorProps定義了 13 個必須鏡像的樣式屬性包括font-size、font-weight、font-family、letter-spacing、word-break、padding-left等。字體相關(guān)屬性決定了文字寬度必須 1:1 復(fù)制否則測量結(jié)果就會失真。第二步把文本切成測量單位reflow()中文本會被拆分成最小測量單位case words: this.units props.text.split(/\b|(?\W)/) // 按單詞切分 break case letters: this.units Array.from(props.text) // 按字符切分 break默認會通過 ASCII 正則猜測純英文按單詞words切含中文等多字節(jié)字符按字符letters切。每個單位被包進一個span classLinesEllipsis-unit放進隱藏 Canvas 中。第三步用 offsetTop 數(shù)出每一行這是整套算法最精妙的一步。calcIndexes()遍歷所有 unit span通過比較相鄰 span 的offsetTop判斷是否換行if (elt.offsetTop offsetTop) { line indexes.push(index) // 記錄每行最后一個單位的索引 offsetTop elt.offsetTop }因為所有 span 都在同一個寬度受限的容器里只要offsetTop變大就說明這一單位被擠到了下一行。這樣就能得到每一行結(jié)束位置的索引數(shù)組indexes。第四步精確放置省略號putEllipsis()先取出第maxLine 1行的起始索引截斷文本在末尾拼接一個wbr和省略號 span。隨后進入一個 while 循環(huán)只要省略號與上一行不在同一行offsetTop不同或比上一行更高offsetHeight更大就繼續(xù)刪除前面的單位直到省略號恰好落在最后一行的結(jié)尾。while (ndPrevUnit ( ndEllipsis.offsetTop maxOffsetTop || // IE/Edge 不支持 wbr ndEllipsis.offsetHeight ndPrevUnit.offsetHeight || ndEllipsis.offsetTop ndPrevUnit.offsetTop )) { this.canvas.removeChild(ndPrevUnit) units.pop() }這一步保證了省略號永遠不會被擠到下一行單獨顯示。第五步把結(jié)果同步回真實 DOM測量完成后組件調(diào)用setState把截斷后的文本渲染到真實組件中如果設(shè)置了trimRight還會用正則[\s\uFEFF\xA0]$去掉行尾空白防止省略號出現(xiàn)在空行上。通過onReflow回調(diào)你還能拿到{ clamped, text }結(jié)果用于二次處理。三個關(guān)鍵源碼文件速覽文件核心職責關(guān)鍵代碼位置src/common.js定義 canvasStyle 與 13 個鏡像樣式屬性第 1~26 行src/index.jsx測量、截斷、渲染主流程reflow第 91 行、calcIndexes第 117 行、putEllipsis第 139 行src/responsiveHOC.jsx150ms 防抖監(jiān)聽 resize 并觸發(fā)重算第 5~42 行進階富文本省略與響應(yīng)式適配富文本支持src/html.jsx的 HTMLEllipsis 通過遞歸遍歷 DOM 節(jié)點hookNode把文本節(jié)點也拆成 unit span復(fù)用同一套測量邏輯甚至支持ellipsisHTML自定義省略號樣式。響應(yīng)式適配responsiveHOC用 lodash 的debounce防抖監(jiān)聽window.resize把winWidth作為 prop 傳入觸發(fā)copyStyleToCanvas重新測量窗口變化時省略位置自動更新。輕量替代src/loose.jsx直接用WebkitLineClamp配合maxHeight做 fallback適合追求性能、且目標瀏覽器兼容的場景。隱藏 Canvas 測量法與 CSS line-clamp 怎么選? 選 react-lines-ellipsis需要跨瀏覽器一致表現(xiàn)、要自定義省略號、要支持富文本、需要onReflow回調(diào)感知截斷狀態(tài)。? 選 CSS line-clamp純文本、目標環(huán)境固定為 WebKit 內(nèi)核、對首屏性能極其敏感、無需感知截斷結(jié)果??偨Y(jié)react-lines-ellipsis 用不到 200 行代碼就把多行省略這個難題拆解成了樣式鏡像、單位切分、行索引計算、省略號定位四個清晰步驟。隱藏 Canvas 測量法的核心思想——在看不見的容器里用真實布局引擎模擬渲染再讀取幾何信息——不僅是多行省略的通用解法也值得你在做文本測量、自適應(yīng)布局時借鑒。如果你正在為 React 項目的多行文本截斷頭疼不妨 clone 下來跑一遍示例源碼雖短卻處處是前端性能與布局的巧思?!久赓M下載鏈接】react-lines-ellipsisSimple multiline ellipsis component for React.JS項目地址: https://gitcode.com/gh_mirrors/re/react-lines-ellipsis創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考