资讯专栏INFORMATION COLUMN

教你实现React文字展开收起组件

3403771864 / 989人阅读

  今天我们讲讲项目中实战就是文字展开收起组件的实现过程,讲解这个就是为了让多给大家一个思路,想法。

  简单来说文字展开收起组件产生的需求背景,就是为省略显示,然后有展开收起的按钮可以操作。我们看显示效果上图:

  上图是文字收起的图示,超过一定的字数那就收起省略显示,并出现查看全部按钮。

  上图显示的就是操作了查看全部按钮之后,文字需要全部显示出来并有收起按钮。还是来看一张gif图的显示最后该组件完成后的效果,如下图:

  开发

  该组件继续使用React+typescript的技术栈,要是没有使用此技术栈的同学就只有参考实现思路,后续待不忙时再来提供其他技术栈对应的版本。

  文字展开收起组件开发,我们现在就只需要在做的时候考虑一定字数这个问题,超过它截取文字并加上...,然后展开时展示所有文字即可,其它的操作基本是常规操作。我们一起往下看

  1.1 定义组件所需字段


  interface IndexProps {
  content: string; // 文本内容
  maxLen?: number; // 文字最大显示长度
  expandText?: string; // 展开按钮文字
  collapseText?: string; // 收起按钮文字
  contentRender: (text: string, handler: React.ReactNode) => React.ReactNode; // 自定义内容
  onExpand?: (expanded: boolean) => void; // 展开、收起后触发
  }

  运行之后我们就可以看到文字展开收起组件,其中content,contentRender是必须传入的,否则组件会报错,其他字段皆为可选字段,在要用到的时候就会传入,不用就使用组件定义的默认值。

  1.2 获取截断后的文字

  获取截断后的文字,其实是根据字段maxLen来自动获取,maxLen设置的默认值为300,即超过300个文字之后就会被截断。maxLen的值是可以修改的,若你设置为200,即文字超过200就会被截取,故其为可选字段。代码如下:

  /**
  * 获取截断后的文字
  * @param text
  */
  const getText = (text: string): string => {
  return (text || '').slice(0, maxLen) + '...'
  }

  1.3 获取展开收起按钮

  不小人是不是从1.1定义的字段中可以看到,其中contentRender这个字段代表的意思为自定义内容,即该组件的内容是可以自定义的。讲白了说就是在设计的时候,就已经想到组件应用的场景在有点多的情况下,也可以让它是可以根据不同的需求场景来进行自定义的,所以该组件的render内容就只有此方法,如下:

  return (
  <>{contentRender(body, getExpandBtn())}</>
  )

  contentRender方法其实接收两个参数:text代表文本内容,其实就是传入的content,只不过它会根据判断条件判断是否被截取;在组件加载时,就会对其进行如下判断:

  useEffect(() => {
  let contentBody = content || '';
  if (contentBody.length > maxLen) {
  contentBody = getText(contentBody);
  setShowBtn(true);
  }
  setBody(contentBody);
  return () => {
  setExpanded(false);
  setShowBtn(false);
  }
  }, [content]);

  通过上述代码可以获取到需要渲染的文本内容,然后将其赋值给body,即它就是contentRender方法接收的第一个参数。

  而第二个参数handler其实就是这里将要说的,获取展开收起按钮的方法。如下:

  /**
  * 获取展开收起按钮
  * @param status
  */
  const getExpandBtn = (): React.ReactNode => (
  showBtn ? (
  <span
  className="custom-text-expanded-handler"
  onClick={() => expandToggle(!expanded)}
  >{expanded ? collapseText : expandText}
  </span>
  ) : null
  )

  从上可以看到,所谓的自定义其实就是我们可以对参数text进行自定义,可以将其使用div包裹,或者对其样式进行自定义皆是可以的。而在我们的项目中,则是又写一个名词解释组件对其自定义,名词解释组件可在下篇文章中简述。

  1.4 展开收起逻辑

  所谓的展开收起逻辑其实就是让文字省略展示或者全部展示,而在这个过程中可以使用暴露出去的onExpand方法做其他逻辑操作,代码如下:

  /**
  * 展开、收起
  * @param status
  */
  const expandToggle = (status: boolean) => {
  let text = status ? content : getText(content);
  setExpanded(status);
  setBody(text);
  onExpand(status);
  }

  1.5 完整代码

  好了,通过上述的简单介绍,组合代码可以得到文字展开收起组件完整代码。

  1.5.1 逻辑代码

  创建index.tsx文件,并写入如下所示代码:

  import * as React from 'react';
  import {useEffect, useState} from "react";
  import './index.scss';
  interface IndexProps {
  content: string; // 文本内容
  maxLen?: number; // 文字最大显示长度
  expandText?: string; // 展开按钮文字
  collapseText?: string; // 收起按钮文字
  contentRender: (text: string, handler: React.ReactNode) => React.ReactNode; // 自定义内容
  onExpand?: (expanded: boolean) => void; // 展开、收起后触发
  }
  /**
  * 自定义文字展开收起组件
  * @param props
  * @constructor
  */
  const TextExpand = (props: IndexProps) => {
  const {
  content,
  maxLen = 300,
  expandText = '查看全部',
  collapseText = '收起',
  contentRender = (text: string, handler: React.ReactNode) => {},
  onExpand = (expanded: boolean) => {},
  } = props;
  const [body, setBody] = useState<any>(null);
  const [expanded, setExpanded] = useState<boolean>(false);
  const [showBtn, setShowBtn] = useState<boolean>(false);
  useEffect(() => {
  let contentBody = content || '';
  if (contentBody.length > maxLen) {
  contentBody = getText(contentBody);
  setShowBtn(true);
  }
  setBody(contentBody);
  return () => {
  setExpanded(false);
  setShowBtn(false);
  }
  }, [content])
  /**
  * 获取截断后的文字
  * @param text
  */
  const getText = (text: string): string => {
  return (text || '').slice(0, maxLen) + '...'
  }
  /**
  * 获取展开收起按钮
  * @param status
  */
  const getExpandBtn = (): React.ReactNode => (
  showBtn ? (
  <span
  className="custom-text-expanded-handler"
  onClick={() => expandToggle(!expanded)}
  >{expanded ? collapseText : expandText}
  </span>
  ) : null
  )
  /**
  * 展开、收起
  * @param status
  */
  const expandToggle = (status: boolean) => {
  let text = status ? content : getText(content);
  setExpanded(status);
  setBody(text);
  onExpand(status);
  }
  return (
  <>{contentRender(body, getExpandBtn())}</>
  )
  }
  export default TextExpand;

  1.5.2 样式代码

  创建index.scss文件,同样写入如下代码即可:

  .custom-text-expanded-handler {
  margin-left: 6px;
  color: #545FD6;
  &:hover {
  color: #1890ff;
  cursor: pointer;
  }
  }

  1.6 安装使用组件

  组件写好,那就来使用它。该组件已经发布到npm上了,所以小伙伴们可以到npm上查看并下载,也可以通过如下命令进行安装使用:

  1

  npm i react-text-expand-collapse 或 yarn add react-text-expand-collapse

  安装好之后,在项目中引用使用:

  // 引入组件
  import TextExpand from 'react-text-expand-collapse/src/index';
  // 使用
  <div style={{
  width: 500,
  margin: '10px auto 0',
  color: '#333',
  fontSize: '12px',
  textAlign: 'left',
  backgroundColor: '#fff'
  }}>
  <TextExpand
  content={str}
  maxLen={100}
  contentRender={(text: string, handler: any) => {
  return (
  <>
  <span>{text}</span>
  {handler}
  </>
  )
  }}
  />
  </div>

  最后实现效果,如下图:

  文章内的代码有需要也可以直接拷走使用,也可以应用在项目中,帮助大家解决问题。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/127976.html

相关文章

  • React Native 中切换TextInput保持键盘展开

    摘要:传给回调函数的里,包含一个触摸事件参数。官网的版文档中,和组件中都有属性,这个属性接收一个回调函数,函数原型是,在组件和的组件的时候触发该事件,传给回调函数的里,参数,其中的属性为该组件的。 1、问题 问题场景: 由于手机屏幕高度不定,做表单页面时,外层通常加上ScrollView组件,使其能够适应屏幕进行滚动。业务需要里面放置多个TextInput组件。 问题描述: 出现的问题是,首...

    xiangzhihong 评论0 收藏0
  • 支持多框架的组件库KPC 1.0正式发布

    摘要:自从年月份对外公布以来,已经经过了个月的迭代,期间发布了几十个正式版本,但一直没有到,因为我们觉得是个里程碑版本,我们必须做的足够完善才敢称之为。 自从17年11月份对外公布以来,KPC已经经过了8个月的迭代,期间发布了几十个正式版本,但一直没有到1.0,因为我们觉得1.0是个里程碑版本,我们必须做的足够完善才敢称之为1.0。而如今我们有信心对外宣布:KPC 1.0终于来了! 其实距离...

    刘厚水 评论0 收藏0
  • 工作记录:不定宽度展开收起卡片

    摘要:写在前面的唠简单记录一下工作中出现的需求和常见的问题,时常记录总结,希望能在之后的工作中吸取经验教训,提高工作效率。只展示一行数据的时候给固定高度为了显示展开收起按钮,因为设定分辨率是来回变的,思来想去还是使用了监听事件。 写在前面的唠 简单记录一下工作中出现的需求和常见的问题,时常记录总结,希望能在之后的工作中吸取经验教训,提高工作效率。如果可以帮助有同样问题的同学我会很开心的,有的...

    leon 评论0 收藏0
  • React hooks写了一个日历组件,来看看?

    摘要:然后使用,在的上绑定了,很简单。日历遍历的思路这一次的提交主要是确定了日历组件,怎么写,具体思路看下面的代码,尽量通过注释把思路讲的清楚一些。前言 在最近的项目中,大量的尝试了react hooks,我们的组件库用的是Next,除了一个地方因为要使用Form + Field的组合,所以使用了class组件,经过了这个项目,也算是总结一些使用的经验,所以准备自己封装一个日历组件来分享一下。以下...

    cangck_X 评论0 收藏0

发表评论

0条评论

3403771864

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<