blog icon indicating copy to clipboard operation
blog copied to clipboard

基于react-multi-clamp实现的多行文本收起展开

Open xianzou opened this issue 2 years ago • 0 comments

基于react-multi-clamp实现的多行文本收起展开

经常有需求需要文本超过指定行数实现收起展开,该组件即可实现该需求;

代码实现

MultiClamp.scss

.collapse{
    color: #07b!important;
    cursor: pointer;
    display: inline;
}

MultiClamp.js

import styles from './MultiClamp.scss';
import React, { useRef, useImperativeHandle, forwardRef } from 'react';
import ReactMultiClamp from 'react-multi-clamp';
import { v4 as uuidv4 } from 'uuid';

const MultiClamp = ({ 
        clamp = 3, 
        putText:'收起',
        downText:'展开',
        onToggle,
        children 
    }, ref) => {

    const multiClampRef = useRef(null);

    const multiClampDwonRef = useRef(uuidv4());

     const firstRenderRef = useRef(0);

    const put = () => {
       multiClampRef.current.multiClamp.reload({
            clamp,
            useOriginalText: true,
        });
    };

    const down = () => {
       firstRenderRef.current += 1;
        multiClampRef.current.multiClamp.reload({
            clamp: 'auto',
            useOriginalText: true,
        });
    };
    const onClampStart = ({ needClamp }) => {
        if (needClamp){
            const collapseDown = document.querySelector(`#clamp_${multiClampDwonRef.current}`);

            if (collapseDown){
                collapseDown.removeEventListener('click', put, false);
               collapseDown.innerText = '';
            }
        }
    };
    // 该回调函数在clamp结束时触发,使用原生css裁剪时不会触发
    const onClampEnd = ({didClamp}) => {
        const collapseDown = document.querySelector(`#clamp_${multiClampDwonRef.current}`);

        if (collapseDown && firstRenderRef.current){
            collapseDown.addEventListener('click', put, false);
            collapseDown.innerText = '收起';
        }
        //收起暂开之后的回调事件 didClamp可以用来区分收起、展开结束
        onToggle && onToggle(didClamp)
    };

    useImperativeHandle(ref, () => ({
        reset: put
    }));

    const clampStateText = {
        dowm: <div className={styles.collapse} onClick={down} >{downText}</div>
    };

    return (
        <ReactMultiClamp
            ellipsis={clampStateText.dowm}
            clamp={clamp}
            ref={multiClampRef}
            onClampStart={onClampStart}
            onClampEnd={onClampEnd}
        >
            {children}
            <span id={`clamp_${multiClampDwonRef.current}`} className={styles.collapse} />
        </ReactMultiClamp>
    );
};

export default forwardRef(MultiClamp);

使用

`引入:import MultiClamp`;

<MultiClamp
    clamp={3}
>
     事件描述:在税务检查过程中,邓伦能够积极配合检查并主动补缴税款4455.03万元,同时主动报告税务机关尚未掌握的涉税违法行为。综合考虑上述情况,上海市税务局第四稽查局依据《中华人民共和国个人所得税法》《中华人民共和国税收征收管理法》《中华人民共和国行政处罚法》等相关法律法规规定,按照《上海市税务行政处罚裁量基准》,对邓伦追缴税款、加收滞纳金并处罚款,共计1.06亿元。其中,对其虚构业务转换收入性质虚假申报偷税但主动自查补缴的4455.03万元,处0.5倍罚款计2227.52万元;对其虚构业务转换收入性质虚假申报偷税但未主动自查补缴的310.79万元,处4倍罚款计1243.16万元。日前,上海市税务局第四稽查局已依法向邓伦送达税务行政处理处罚决定书。《中华人民共和国税收征收管理法》第六十三条第一款规定,对纳税人偷税的,由税务机关追缴其不缴或者少缴的税款、滞纳金,并处不缴或者少缴的税款百分之五十以上五倍以下的罚款。我局坚持依法依规、过罚相当的原则,充分考虑了违法行为的事实、性质、情节和社会危害程度等因素对邓伦进行处罚。一方面,对其主动纠错的偷逃税等违法行为依法从轻处理。邓伦积极配合检查并主动补缴税款,同时主动报告税务机关尚未掌握的涉税违法行为,具有主动减轻违法行为危害后果等情节。我局依据《中华人民共和国税收征收管理法》《中华人民共和国行政处罚法》等有关规定,按照《上海市税务行政处罚裁量基准》,对邓伦虚构业务转换收入性质虚假申报偷税但主动自查补缴税款部分处0.5倍罚款。另一方面,对其未能纠错的违法行为依法严肃处理。邓伦虚构业务转换收入性质虚假申报偷税且未主动自查补缴部分,性质恶劣。我局依据《中华人民共和国税收征收管理法》《中华人民共和国行政处罚法》等有关规定,按照《上海市税务行政处罚裁量基准》,对其予以从重处罚,处4倍罚款。
</MultiClamp>

对外暴露出 reset方法 如果有外层div宽度变化 需要从新渲染 用法如下:

import {useUpdateEffect,useSize} from 'ahooks';
const multiClampRef = useRef();
const size = useSize(leftBarRef);

useUpdateEffect(() => {
    multiClampRef.current.reset();
}, [size?.width]);

<div
    className={isToggle ? `${styles.leftBarToggle}` : `${styles.leftBarResize}`}
    ref={leftBarRef}
>
    <MultiClamp
        clamp={3}
         ref={multiClampRef}
    >
        。。。
    </MultiClamp>
</div>

示例

收起状态: image-20220316103416830 展开状态: image-20220316103416830

FAQ

1、收起的时候为什么使用dom元素操作进行down的事件绑定?

因为react-multi-clamp传递进去的是纯文本,没有办法进行事件预先绑定或者通过ref等形式;

xianzou avatar Mar 16 '22 02:03 xianzou