欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript實現(xiàn)文本中間縮略的兩種方案

 更新時間:2024年06月24日 11:04:48   作者:碎_浪  
項目中經(jīng)常會遇到縮略展示文字的場景,即要求文字在一行不換行展示,超出自動展示...,常用的展示效果有兩種,文字中間縮略以及文字末尾縮略,本文將通過代碼示例給大家詳細的講一下這兩種方案,需要的朋友可以參考下

前言

項目中經(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)聽versiontext的變化,先重置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)文章

最新評論