封装Ellipsis组件,亲测使用各种场景
自己封装了Ellipsis组件 基于react+taro,以下是实现代码,分为JSX和CSS文件
JSX代码如下:
import { FC, Fragment, JSX, useState } from 'react';
import { Image, StandardProps, Text, View } from '@tarojs/components';import iconDropDown from '@/assets/icons/icon-dorpdown-primary.svg';
import useBoundingClientRect from '@/hooks/useBoundingClientRect';import './index.less';interface EllipsisProps {rows?: number;/*** 收起节点*/foldRender?: JSX.Element;/*** 是否显示收取按钮*/showFold?: boolean;/*** 展开节点*/unfoldRender?: JSX.Element;/*** 是否显示展开按钮*/showUnfold?: boolean;onChange?: (val: boolean) => void;
}const Ellipsis: FC<EllipsisProps & StandardProps> = ({rows = 1,children,className,showUnfold,unfoldRender,
}) => {const [show, setShow] = useState(false);const [rectAssist] = useBoundingClientRect('#rectAssist', [children]);const [rectActual] = useBoundingClientRect('#rectActual', [children]);const style = {lineClamp: rows,webkitLineClamp: rows,};const showMoreBtn =!show &&showUnfold &&rectActual?.height &&rectAssist?.height &&Number(rectActual?.height) !== Number(rectAssist?.height);return (<Fragment><Viewstyle={{ position: 'absolute', left: 0, top: -999999, opacity: 0 }}className={className}id="rectAssist">{children}</View><ViewclassName={`lineClamp__1 ${className}`}style={!show ? style : { display: 'block' }}id="rectActual">{children}{!!showMoreBtn && (<View className="unfold-wrap" id="unfoldWrap" onClick={() => setShow(true)}>{unfoldRender || (<View className="unfold-btn"><Text>查看更多</Text><Image src={iconDropDown} /></View>)}</View>)}</View></Fragment>);
};export default Ellipsis;
其中useBoundingClientRect 是自定义的hook,代码如下
import React, { useEffect, useState } from 'react';
import Taro, { NodesRef } from '@tarojs/taro';const useBoundingClientRect = (selector: string,deps?: React.DependencyList,
): [rect: NodesRef.BoundingClientRectCallbackResult | undefined] => {const [rect, setRect] = useState<NodesRef.BoundingClientRectCallbackResult | NodesRef.BoundingClientRectCallbackResult[]>();useEffect(() => {Taro.nextTick(() => {Taro.createSelectorQuery().select(selector).boundingClientRect((respRect) => {setRect(respRect);}).exec();});}, [...(deps || [])]);return [rect as any];
};export default useBoundingClientRect;
Css代码如下,目前在项目中使用less预编译处理器
.lineClamp(@row) {display: -webkit-box;overflow: hidden;line-clamp: @row;-webkit-line-clamp: @row;-webkit-box-orient: vertical;position: relative;
}.lineClamp__1 {.lineClamp(1);&::after {color: red;position: absolute;right: 0;bottom: 5px;}
}.lineClamp__2 {.lineClamp(2);
}.lineClamp__3 {.lineClamp(3);
}.unfold-wrap {position: absolute;right: 0;bottom: 0;display: flex;background: linear-gradient(to left, #fff, #fff, #fff, rgba(255, 255, 255, 0.4));
}.unfold-btn {display: flex;flex-direction: row;align-items: center;min-width: 32px;padding: 4px 10px 4px 30px;line-height: 1;text {color: #b89962;font-size: 12px;font-style: normal;font-weight: 400;line-height: 12px; /* 100% */}image {width: 13px;height: 12px;}
}
效果如下: