在 React 中自动缩放输入值的宽度

cab*_*nto 15 javascript resize reactjs react-hooks

我想要一个宽度适应其内容的输入。

我正在尝试实现类似问题的答案,但使用 React:

import React, { useState } from 'react';

export default () => {
  const [content, setContent] = useState('');
  const [width, setWidth] = useState(0);

  const changeHandler = evt => {
    setContent(evt.target.value);
  };

  return (
    <wrapper>
      <span id="hide">{content}</span>
      <input type="text" autoFocus style={{ width }} onChange={changeHandler} />
    </wrapper>
  );
};
Run Code Online (Sandbox Code Playgroud)

问题是我不知道如何查询跨度的宽度,以便更改输入的宽度(使用setWidth)。

我怎样才能实现这个目标?

cab*_*nto 27

经过一番折腾,我找到了解决方案!

import React, { useState, useRef, useEffect } from 'react';

export default () => {
  const [content, setContent] = useState('');
  const [width, setWidth] = useState(0);
  const span = useRef();

  useEffect(() => {
    setWidth(span.current.offsetWidth);
  }, [content]);

  const changeHandler = evt => {
    setContent(evt.target.value);
  };

  return (
    <wrapper>
      <span id="hide" ref={span}>{content}</span>
      <input type="text" style={{ width }} autoFocus onChange={changeHandler} />
    </wrapper>
  );
};
Run Code Online (Sandbox Code Playgroud)

#hide为了获得我所使用的跨度的参考useRef。然后,width状态变量可以通过内部定义的函数进行更新useEffect,每次更改时都会调用该函数content

我还必须在for和display: none的 css 中切换,否则总是会计算为 0。#hideposition: absoluteopacity: 0targetRef.current.offsetWidth

这是一个工作演示


ent*_*ull 7

嗯,这很有趣!我尝试了一些不同的想法,但没有一个能完美地工作——尤其是如果它们是用某种受人尊敬的代码编写的。

然而我发现了这篇文章并决定尝试一下。 /sf/answers/3044222961/

我确信它有缺陷,例如,除非我使用等宽字体,否则它确实很有趣。但也许有一些 CSS 技巧可以解决这个问题?

// Normally I'd go for ES6 imports, but to make it run as a StackOverflow snippet I had to do it this way
const { useState, useRef } = React;

const GrowingInput = () => {
  const [width, setWidth] = useState(0);
  
  const changeHandler = evt => {
    setWidth(evt.target.value.length);
  };
 
  return (
    <input style={{ width: width +'ch'}} type="text" autoFocus onChange={changeHandler} />
  )
};

const App = () => {
  return (
    <p>Lorem ipsum {<GrowingInput />} egestas arcu.</p>
  );
};

// Render it
ReactDOM.render(<App />, document.getElementById("react"));
Run Code Online (Sandbox Code Playgroud)
input {
  font-family: Courier;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
Run Code Online (Sandbox Code Playgroud)

您是否考虑过使用 acontenteditable来代替?

https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Editable_content