文本省略组件【react - h5】

组件支持业务:

  1. 传入isExpand=true 可以支持,传入展开收起按钮可以显示文本是否展示全部或省略文本
  2. 传入moreShow=true 可以支持,文本超过行时显示更多按钮,点击更多按钮可以传入点击事件,文本不超过两行时,显示发送按钮,此时点击发送按钮可以传入发送按钮事件
  3. 如果业务有需求,大于一行和一行后边有交互逻辑,此组件也是可以实现

组件代码:
data.d.ts文件

interface EllipsisProps {
  /**
   * 必传项,文本内容
   * @defaultValue ''
   */
  content: string
  /**
   * 非必传项,默认百分之百
   * @defaultValue 100%
   */
  width?: number
  /**
   * 非必传,展开按钮
   * @defaultValue ''
   */
  customButton?: ReactDOM
  /**
   * 非必传项,收起按钮
   * @defaultValue ''
   */
  collapseButton?: ReactDOM
  /**
   * 默认展示几行
   * @defaultValue 2行
   */
  rows?: number
  /**
   * 非必传项,文本的行高
   * @defaultValue ''
   */
  lineHeight?: number
  /**
   * 非必传项,文本的字体大小
   * @defaultValue ''
   */
  fontSize?: number
  /**
   * 非必传项,文本的字体颜色
   * @defaultValue ''
   */
  color?: string
  /**
   * 非必传项,点击之后是否展开全部,默认为true
   * @defaultValue true
   */
  whetherToExpandAll?: boolean
  /**
   * 非必传项,点击之后是否展开全部,如果是whetherToExpandAll false 则告知父组件我点击了展开按钮
   * @defaultValue true
   */
  whetherToExpandClick?: () => void
  /**
   * 非必传项,点击之后如果不展开全部,则通知父组件,并且告知是否是超过一行 大于一行则为true
   * @defaultValue -
   */
  whetherToClick?: (val: boolean) => void
  /**
   * 判断是否显示 发送或更多按钮
   * @defaultValue
   */
  moreShow?: boolean
  /**
   * 发送按钮事件
   * @defaultValue
   */
  shareChat?: () => void
  /**
   * 控制是否显示展开 收起按钮
   * @defaultValue
   */
  isExpand?: boolean
  /**
   * 更多弹窗事件
   * @defaultValue
   */
  textShow?: () => void
}

export { EllipsisProps }

index.tsx 文件

import { useBoolean, useReactive } from 'ahooks'
import React, { useEffect, useRef } from 'react'
import { EllipsisProps } from './data'
import { ContentArea } from './styled'
const Ellipsis: React.FC<EllipsisProps> = (props) => {
  const {
    width,
    content = '',
    customButton,
    collapseButton,
    rows = 2,
    lineHeight = 22,
    fontSize = 14,
    color = '#262626',
    whetherToExpandAll = true,
    whetherToExpandClick,
    whetherToClick,
    moreShow,
    shareChat,
    textShow,
    isExpand,
  } = props
  const ref = useRef<HTMLDivElement>(null)
  // 控制展开收起
  const [open, { toggle }] = useBoolean(false)
  const state = useReactive({
    isShow: false,
  })
  useEffect(() => {
    // 总体高度
    const scrollHeight = ref.current?.scrollHeight || 0
    // 可视高度
    const clientHeight = ref.current?.clientHeight || 0

    if (scrollHeight <= clientHeight) {
      ref.current?.classList.add('trunk')
    } else {
      ref.current?.classList.remove('trunk')
    }
    // 如果不进行展开收起,则初始进入告知父组件是否是超过一行
    if (!whetherToExpandAll) {
      // 获取元素的行高
      const lineHeight = window.getComputedStyle(
        ref.current as Element,
        null
      ).lineHeight
      state.isShow = scrollHeight <= clientHeight ? false : true
      // 转化行高为数字
      const initLineHeight = parseInt(lineHeight.split('px')[0])
      // 如果行高加上6px 的偏差 小于可视高度的话,呢么表示超过一行
      whetherToClick && whetherToClick(initLineHeight + 6 <= clientHeight)
    }
  }, [ref && ref.current])

  // 点击展开收起
  const toggles = () => {
    if (whetherToExpandAll) {
      toggle()
    } else {
      whetherToExpandClick && whetherToExpandClick()
    }
  }

  return (
    <ContentArea
      lineHeight={lineHeight}
      fontSize={fontSize}
      color={color}
      rows={!open ? rows : 9999}
      width={width ? width + 'px' : '100%'}
      content={content}
      isShow={state.isShow}
      moreShow={moreShow}
    >
      <div onClick={toggles} className="textord" ref={ref}>
        {isExpand && (
          <div onClick={toggles} className="expand">
            {!open ? customButton : collapseButton}
          </div>
        )}
        <span
          style={{ whiteSpace: 'pre-wrap' }}
          dangerouslySetInnerHTML={{ __html: content }}
        ></span>
        {moreShow && (
          <span
            className={state.isShow ? 'more' : 'send'}
            onClick={state.isShow ? textShow : shareChat}
          >
            {state.isShow ? '更多' : '发送'}
          </span>
        )}
      </div>
    </ContentArea>
  )
}
export default Ellipsis

styled.ts 文件

import styled from 'ns-styled'
const ContentArea = styled.div<{
  width: string
  rows: number
  content: string
  lineHeight: number
  fontSize: number
  color: string
  moreShow: boolean | undefined
  isShow: boolean
}>`
  display: flex;
  .textord {
    position: relative;
    width: ${(p) => p.width};
    max-height: ${(p) => p.rows * 22 + 'px'};
    line-height: ${(p) => p.lineHeight + 'px'};
    font-size: ${(p) => p.fontSize + 'px'};
    color: ${(p) => p.color};
    overflow: hidden;
    &::before {
      content: '';
      position: absolute;
      right: 0;
      bottom: 0;
      height: calc(100% - 20px);
      min-width: 50px;
      background-color: #f5f5f5;
    }
    .expand {
      float: right;
      clear: both;
      height: 20px;
      line-height: 20px;
      position: relative;
      min-width: 37px;
      cursor: pointer;
      height: 100%;
      text-align: right;
      div,
      span {
        display: inline-block;
      }
    }
    .more {
      position: absolute;
      right: 0;
      bottom: 0px;
      height: 22px;
      cursor: pointer;

      &::before {
        content: '...';
        position: absolute;
        line-height: 0px;
        height: 6px;
        bottom: 5px;
        color: #333;
        transform: translateX(-15px);
      }
    }
    .send {
      font-size: 12px;
      color: #0d5dff;
      font-weight: 500;
      margin-left: 8px;
      cursor: pointer;
    }
  }
  .trunk {
    .expand,
    .more {
      display: none;
    }
  }
`
export { ContentArea }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值