React 中确定 div 中文本的行数

Jam*_*son 9 html javascript css reactjs

我使用 Line-Clamp 属性(带有备份最大高度)来限制 React 组件中显示的行数。我希望之后有一个可选链接,可以将此内容扩展到其完整长度,但前提是当前行数大于行夹数。

行数是固定的 (3),所以我想我可以计算 div 的当前高度,然后将其与标准文本大小的 3 行的预期高度进行比较?

但是,如果有人决定在其中放入不同的非文本内容,它可能无法按预期工作。有没有特定的方法来获取容器中文本的行数?

 const {useState} = React;

const ClampedDiv = ({ children, showLinkProp }) => {
  const [open, setOpen] = useState(false);

  // This is where I'd do the line number calculation, but it's just
  // using a placeholder instead.
  let showLink = false;
  if (showLinkProp) {
    showLink = true;
  }
  
  let textClass = "text";
  if (open) {
    textClass += " open";
  }

  return <div className="container">
    <span class={textClass}>{children}</span>
    {showLink && !open && (
      <button onClick={() => setOpen(true)}>Open</button>
    )}
  </div>
};

const Component = () => (
  <React.Fragment>
    <ClampedDiv>
      Some content that should not show a read more
    </ClampedDiv>
    <ClampedDiv showLinkProp>
      Some content that should show a read more. Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
    </ClampedDiv>
  </React.Fragment>
);

ReactDOM.render(
  <Component />,
  document.body
)
Run Code Online (Sandbox Code Playgroud)
.text {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  max-height: calc(3 * 1.5 * 14px);
  font-size: 14px;
  line-height: 1.5;
}

.open {
  -webkit-line-clamp: unset;
  max-height: none;
}

.container {
  background-color: crimson;
  color: white;
  margin-bottom: 15px;
  padding: 15px;
}
Run Code Online (Sandbox Code Playgroud)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
    <div id="react"></div>
Run Code Online (Sandbox Code Playgroud)

小智 3

如果您只想检查元素内的隐藏内容,则可以使用钩子useRef引用特定元素。

然后,使用scrollHeight获取元素内容的高度。

Element.scrollHeight 只读属性是元素内容高度的度量,包括由于溢出而在屏幕上不可见的内容。

并与它进行比较,clientHeight看看是否有隐藏内容。

 const { useState, useRef, useLayoutEffect } = React;

const ClampedDiv = ({ children }) => {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);

  // This is where I'd do the line number calculation, but it's just
  // using a placeholder instead.
  const [showLink, setShowLink] = useState(false);
  
  useLayoutEffect(() => {
      if (ref.current && ref.current.clientHeight < ref.current.scrollHeight) {
        setShowLink(true)
      }
  }, [ref])
  
  let textClass = "text";
  if (open) {
    textClass += " open";
  }

  return <div className="container">
    <span class={textClass} ref={ref}>{children}</span>
    {showLink && !open && (
      <button onClick={() => setOpen(true)}>Open</button>
    )}
  </div>
};

const Component = () => (
  <React.Fragment>
    <ClampedDiv>
      Some content that should not show a read more
    </ClampedDiv>
    <ClampedDiv>
      Some content that should show a read more. Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop penter code hereublishing software like Aldus PageMaker including versions of Lorem Ipsum.
    </ClampedDiv>
  </React.Fragment>
);

ReactDOM.render(
  <Component />,
  document.body
)
Run Code Online (Sandbox Code Playgroud)
.text {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  max-height: calc(3 * 1.5 * 14px);
  font-size: 14px;
  line-height: 1.5;
}

.open {
  -webkit-line-clamp: unset;
  max-height: none;
}

.container {
  background-color: crimson;
  color: white;
  margin-bottom: 15px;
  padding: 15px;
}
Run Code Online (Sandbox Code Playgroud)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
    <div id="react"></div>
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,现在显示更多内容的检查的实现是特定于子组件的,并且取决于父组件传递的内容。