8000 React超出指定行数显示全文 · Issue #33 · xianzou/blog · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
React超出指定行数显示全文 #33
Open
@xianzou

Description

@xianzou

React文本超出指定行数显示全文,点击全文可以展开和收起

示例图片:

TextEllipsis.js

import styles from './TextEllipsis.scss';
import React, { useState, useRef, Fragment, useLayoutEffect } from 'react';

/**
 * 多行文本溢出显示省略号组件
 */
const TextEllipsis = ({ content, headerText }) => {
    const contentRef = useRef({});
    const [showAll, setShowAll] = useState(false);
    const [needHidden, setNeedHidden] = useState(false); // 超出4行需要隐藏
    const [isCompute, setIsCompute] = useState(false);

    /**
     * @description: 处理content文案的点击展开收起
     * @return: null
     */
    const handleContent = e => {
        e.stopPropagation();

        setShowAll(!showAll);
    };
    // 判断文本超出行数
    const isElementCollision = (ele, rowCount = 6, cssStyles, removeChild) => {
        if (!ele) {
            return false;
        }
        const clonedNode = ele.cloneNode(true);
        // if(clonedNode.innerHTML){

        // }
        // 给clone的dom增加样式
        clonedNode.style.overflow = 'visible';
        clonedNode.style.display = 'inline-block';
        clonedNode.style.width = 'auto';
        clonedNode.style.whiteSpace = 'nowrap';
        clonedNode.style.visibility = 'hidden';
        clonedNode.style.whiteSpace = 'pre-wrap'; //支持换行
        // 将传入的css字体样式赋值
        if (cssStyles) {
            Object.keys(cssStyles).forEach(item => {
                clonedNode.style[item] = cssStyles[item];
            });
        }

        // 给clone的dom增加id属性
        const _time = new Date().getTime();

        const containerID = `collision_node_id_${_time}`;

        clonedNode.setAttribute('id', containerID);

        const tmpNode = document.getElementById(containerID);
        let newNode = clonedNode;

        if (tmpNode) {
            document.body.replaceChild(clonedNode, tmpNode);
        } else {
            newNode = document.body.appendChild(clonedNode);
        }
        // 新增的dom宽度与原dom的宽度*限制行数做对比
        // 一行是25高度,根据样式TextEllipsis.scss的textContent的样式line-height: px2rem(50);
        const defaulltHeight = rowCount * 25;
        let differ = false;

        if (newNode.offsetHeight > defaulltHeight){
            differ = true;
        }

        if (removeChild) {
            document.body.removeChild(newNode);
        }
        return differ;
    };

    useLayoutEffect(() => {
        const cssStyles = { fontWeight: '400' };

        const needHiddenValue = isElementCollision(contentRef.current, 6, cssStyles, true);

        setNeedHidden(needHiddenValue);
        setIsCompute(true);
    }, [contentRef]);

    return (
        <div className={styles.textEllipsis}>
            <div style={{ opacity: isCompute ? 1 : 0 }}>
                <div
                    ref={contentRef}
                    className={`${styles.textContent} ${!showAll && needHidden ? styles['hidden-text'] : ''}`}
                >
                    {headerText ? headerText() : null}
                    {content}
                </div>
            </div>
            {
                !isCompute && (
                    <Fragment>
                        <div className={styles.bgLoad} />
                        <div className={styles.bgLoad} />
                    </Fragment>
                )
            }
            {isCompute && needHidden && (
                <div
                    className={styles['content-btn']}
                    onClick={e => {
                        handleContent(e);
                    }}
                >
                    {!showAll ? '全文' : '收起'}
                </div>
            )}
        </div>
    );
};

export default TextEllipsis;

TextEllipsis.scss

.textContent {
    font-size: px2rem(30);
    font-family: PingFangSC-Regular, PingFang SC;
    font-weight: 400;
    color: rgba(0, 0, 0, 1);
    line-height: px2rem(50);
    word-wrap:break-word; 
    word-break:break-all;
    white-space: pre-wrap;
}

.hidden-text {
    display: -webkit-box;
    -webkit-line-clamp: 6;
    /*! autoprefixer: off */
    -webkit-box-orient: vertical;
    /* autoprefixer: on */
    overflow: hidden;
}

.content-btn {
    font-size: px2rem(26px);
    font-family: PingFangSC-Regular, PingFang SC;
    font-weight: 600;
    color: #4CCD93;
    line-height: px2rem(48px);
    margin-top: px2rem(10px);
}

.bgLoad{
    background-image: linear-gradient(90deg, #f0f0f0 25%, #e3e3e3 37%, #f0f0f0 63%);
    background-size: 400% 100%;
    height: px2rem(40);
    animation: loading 1.4s ease infinite;
}
.bgLoad+.bgLoad{
    width: 90%;
    margin-top: px2rem(12);
}
 @keyframes loading {
        0% {
            background-position: 100% 50%
        }
    
        to {
            background-position: 0 50%
        }
    }

使用

<TextEllipsis content={textContent} />

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0