reactjs 如何在React JS中多读少读

ldxq2e6h  于 12个月前  发布在  React
关注(0)|答案(3)|浏览(117)

我想显示只有20个字符的默认情况下,点击阅读更多按钮后,完整的内容应该是可见的。

import React, { useState } from "react";
import Card from "../pages/Card";
import Servicesdata from "../data/Servicesdata";

const Services = () => {
  return (
    <>
      <section className="services">
        <div className="container mt-5">
          <div className="row">
            <div className="col-md-12">
              <h2 className="text-center heading-style-1">Key Areas</h2>
            </div>
          </div>
          {Servicesdata.map((val, index) => {
            return (
              <Card
                key={index}
                title={val.title}
                desc={val.desc}
                img={val.imgsrc}
                newSrc={val.newSrc}
                id={index}
              />
            );
          })}
        </div>
      </section>
    </>
  );
};

export default Services;

个字符

const Servicesdata = [
  {
    ID: "01",
    title: "Power Generation",
    desc:
      " We have rich experience in building thermal, hydro, and combined cycle power plants. We provide customized ready-to-deploy solutions for power plants including total EPC and comprehensive Balance of Plant (BOP) and Flue-gas desulfurization (FGD) solutions.",
    imgsrc: "https://www.tataprojects.com/images/Transmission-Line.jpg",
    newSrc: "https://www.tataprojects.com/images/Transmission-Line.jpg"
  },

  {
    ID: "02",
    title: "Transmission",
    desc:
      "We have successfully commissioned more than 13,000 kms of transmission lines across multiple voltage levels including 800kv HVDC projects",
    imgsrc: "https://www.tataprojects.com/images/Sunbstations-min.jpg",
    newSrc: "https://www.tataprojects.com/images/Transmission-Line.jpg"
  },
  {
    ID: "03",
    title: "Substations",
    desc:
      "Our optimally designed towers and substation structures allow us to reduce conductor wastage ensuring faster construction and on-time delivery.",
    imgsrc: "https://www.tataprojects.com/images/Tower-Manufactaring-Unit.jpg",
    newSrc: "https://www.tataprojects.com/images/Transmission-Line.jpg"
  },

  {
    ID: "04",
    title: "Tower Manufacturing Unit",
    desc:
      "We have a state-of-the-art manufacturing unit to manufacture transmission line towers and structures. The unit is spread across 40 acres of land.",
    imgsrc: "https://www.tataprojects.com/images/Smart-Grid-min.jpg",
    newSrc: "https://www.tataprojects.com/images/Transmission-Line.jpg"
  }
];

export default Servicesdata;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

的字符串

import React, { useState } from "react";

const Card = props => {
  //Store the currently hovered object's id in the state
  //Initially it'll be ""
  const [currentHoveredId, setCurrentHoveredId] = useState("");

  //On mouse over update the id with the cuurent object's ID
  const onMouseOver = id => {
    setCurrentHoveredId(id);
  };

  //On moving the cursoe out of the image, then reset it to ""
  const onMouseOut = () => {
    setCurrentHoveredId("");
  };

  return (
    <>
      {props.id % 2 !== 0 ? (
        <div className="row featurette align-items-center">
          <div className="col-md-7">
            <h2 className="featurette-heading">{props.title}</h2>
            <p className="lead">{props.desc}</p>
            <a href="#">Read More</a>
          </div>
          <div className="col-md-5">
            <img
              src={currentHoveredId === props.id ? props.newSrc : props.img}
              className={`${
                currentHoveredId === props.id ? "fadeInLeft" : "fadeInRight"
              } img-fluid`}
              onMouseOver={() => {
                onMouseOver(props.id);
              }}
              onMouseOut={onMouseOut}
            />
          </div>
        </div>
      ) : null}

      {props.id % 2 === 0 ? (
        <div className="row featurette align-items-center">
          <div className="col-md-5">
            <img
              src={currentHoveredId === props.id ? props.newSrc : props.img}
              className={`${
                currentHoveredId === props.id ? "fadeInRight" : "fadeInLeft"
              } img-fluid`}
              onMouseOver={() => {
                onMouseOver(props.id);
              }}
              onMouseOut={onMouseOut}
            />
          </div>

          <div className="col-md-7">
            <h2 className="featurette-heading">{props.title}</h2>
            <p className="lead">{props.desc}</p>
            <a href="#">Read More</a>
          </div>
        </div>
      ) : null}
    </>
  );
};

export default Card;


“Lorem ipsum dolor sit amet,consectetur adipiscing elit,sed do eiusmod tempor incidididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,acquiration ullamco laboris nisi ut aliquip ex ea commodo conquat. Duis aute irure dolor in reproductive derit in voluptate velit esse cillum dolore eu fuguat nulla pariatur. Excepteur sint sincidatat cupidatat non proident,sunt in culpa qui officia deserunt mollit anim id est laborum.”

2lpgd968

2lpgd9681#

您可以在卡组件中添加新状态以控制要显示的内容。

const [showFullDescription, setFullDescription] = useState(false);

字符串
然后在你的按钮中,你可以在显示全文或不显示全文之间切换。

const showFullDescriptionHandler = () => {
    setFullDescription(!showFullDescription);
  };

const description = showFullDescription
    ? props.desc
    : props.desc.slice(0, 20);

<div className="col-md-7">
    <h2 className="featurette-heading">{props.title}</h2>
    <p className="lead">{description}</p>
    <button onClick={showFullDescriptionHandler}>
        Read {showFullDescription ? "Less" : "More"}
     </button>
</div>

svmlkihl

svmlkihl2#

这个功能就可以了

function truncateString(str, num) {
  // If the length of str is less than or equal to num
  // just return str--don't truncate it.
  if (str.length <= num) {
    return str
  }
  // Return str truncated with '...' concatenated to the end of str.
  return str.slice(0, num) + '...'
}

truncateString("A-tisket a-tasket A green and yellow basket", 8);

字符串
这是一篇文章的摘录[https://medium.com/@DylanAttal/truncate-a-string-in-javascript-41f33171d5a8](在Javascript中截断)

6pp0gazn

6pp0gazn3#

如果您希望组件接受HTML元素(作为react元素)而不仅仅是字符串,然后根据您指定的限制截断要显示的最终文本,则可以解析输入,访问元素的子元素,直到达到字符串,然后计算字符串中的字符数,在达到最大字符数后截断并停止该过程。
下面是一个执行此操作的组件示例:

import React from 'react';

type ParseResult = {
    content: React.ReactNode | React.ReactNode[];
    remaining: number;
};

type Parse = (root: ParseResult, parse: Parse) => ParseResult;

const parseString = (text: string, remaining: number): ParseResult => {
    if (!text?.length) {
        return { content: text, remaining };
    }

    const newText =
        remaining <= 0
            ? ''
            : text.length > remaining
            ? text.substring(0, remaining)
            : text;

    return { content: newText, remaining: remaining - text.length };
};

const parse: Parse = (root, parseCallback) => {
    const { content, remaining = 0 } = root;

    if (typeof content === 'string') {
        const result = parseString(content, remaining);
        return result;
    } else if (React.isValidElement(content)) {
        const children = (content.props as { children?: React.ReactNode })
            ?.children;

        if (children != null) {
            const innerResult = parseCallback(
                {
                    content: children,
                    remaining,
                },
                parseCallback,
            );
            const newContent = React.cloneElement(content, {}, innerResult.content);
            return { content: newContent, remaining: innerResult.remaining };
        }
    } else if (Array.isArray(content)) {
        const list: React.ReactNode[] = [];
        let newRemaining = remaining;

        for (const child of content) {
            const parsed = parseCallback(
                { content: child, remaining: newRemaining },
                parseCallback,
            );
            newRemaining = parsed.remaining;
            const newContent = (
                <React.Fragment key={list.length}>{parsed.content}</React.Fragment>
            );
            list.push(newContent);

            if (newRemaining < 0) {
                break;
            }
        }

        return { content: list, remaining: newRemaining };
    }

    return root;
};

export interface ReadMoreAdditionalProps {
    expanded?: boolean;
    showMore?: React.ReactNode;
    showLess?: React.ReactNode;
}

const ReadMoreInner: React.FC<
    {
        children: React.ReactNode;
        truncate: number;
    } & ReadMoreAdditionalProps
> = ({ truncate, expanded, showMore, showLess, children }) => {
    const root: ParseResult = {
        content: children,
        remaining: truncate,
    };
    const result = parse(root, parse);

    return (
        <>
            {expanded ? children : result.content}
            {result.remaining < 0 ? (expanded ? showLess : showMore) : undefined}
        </>
    );
};

export interface ReadMoreOptions extends ReadMoreAdditionalProps {
    truncate?: number;
}

export type ReadMoreProps = ReadMoreOptions & {
    children: React.ReactNode;
};

export const ReadMore: React.FC<ReadMoreProps> = ({
    truncate,
    children,
    ...props
}) => {
    return truncate != null ? (
        <ReadMoreInner {...props} truncate={truncate}>
            {children}
        </ReadMoreInner>
    ) : (
        <>{children}</>
    );
};

字符串
请记住,该组件要求子组件包含最终文本(或不包含文本)。它不会访问其他属性(如texttitle属性),但这对于HTML组件应该是没问题的。
上面的组件本身不受HTML的约束,并且除了react之外不需要其他库,因此它也可以在react native中使用。
您可以在代码中包含此组件,添加按钮以显示更多或更少的文本,然后根据需要设置按钮的样式。
我创建了一个库来完成这个任务,如果您不想在项目中添加所有组件代码,我还创建了一个易于自定义的Web组件。
使用以下各项安装库:

npm install react-shorten


下面是如何使用该库的示例:

import { ReadMoreWeb } from 'react-shorten';
import React from 'react';

const StyledReadMore: React.FC<{
    truncate?: number;
    children: React.ReactNode;
}> = ({ truncate, children }) => (
    <ReadMoreWeb
        truncate={100}
        showMoreText="Show more"
        showLessText="Show less"
        className="read-more-btn"
    >
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed
        ullamcorper, odio eu aliquam ultricies, enim sapien aliquet arcu, quis
        aliquam diam massa eu nisl. Sed vitae nunc eget nunc ullamcorper
        aliquet. Sed euismod, nisl eget aliquam ultricies, justo nisl aliquet
        nunc, quis aliquam diam massa eu nisl. Sed vitae nunc eget nunc
        ullamcorper aliquet. Sed euismod, nisl eget aliquam ultricies, justo
        nisl aliquet nunc, quis aliquam diam massa eu nisl. Sed vitae nunc eget
        nunc ullamcorper aliquet.
    </ReadMoreWeb>
);


使用CSS:

.read-more-btn {
    display: inline;
    padding: 0;
    margin: 0;
    font-size: 1rem;
    color: rgb(80, 154, 223);
    background: none;
    border: none;
    cursor: pointer;
}

.link {
    color: rgb(26, 210, 243);
}


您可以看到here网络演示和here本地演示。“
如果不想安装其他库,也可以将这些演示用作参考,并将ReadMoreReadMoreWeb组件直接包含在项目中。

相关问题