如何使用React创建自动缩放输入?

问题描述 投票:0回答:3

我需要一个具有最小宽度和最大宽度的输入,它将根据其内容增大和缩小

javascript html css reactjs
3个回答
2
投票

你必须有状态。它可以作为参数传递(提升状态,当状态位于上层时)或直接在组件中
然后只需使用输入状态的长度

新解决方案

const Input = (props) => {
    const [value, changeValue] = React.useState('');

    return (
        <input
            style={{ width: Math.min(Math.max(value.length, 2), 50) + 'ch' }}
            value={value}
            onChange={(event) => {
                changeValue(event.target.value);
            }}
        />
    );
};

ReactDOM.createRoot(document.getElementById('root')).render(<Input />);
input {
  font-family: "Roboto", monospace;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

Math.min 和 Math.Max 用于使大小介于 min(2) 和 max(20) 之间。没有等宽字体系列,您可以获得其他结果

旧解决方案

const {useState} = React;


const Input = (props) => {
    const [value, changeValue] = useState('');
  
    return (
            <input 
        size={Math.min(Math.max(value.length, 2), 20)}
                value={value}
                onChange={(event) => {changeValue(event.target.value);}}
            />
    );
}

ReactDOM.createRoot(
    document.getElementById("root")
).render(
    <Input />
);
input {
  font-family: "Roboto", monospace;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>


1
投票
import React, {
  type CSSProperties,
  type InputHTMLAttributes,
  useEffect,
  useRef,
  useState
} from 'react'

const sizerStyle: CSSProperties = {
  position: 'absolute',
  top: 0,
  left: 0,
  visibility: 'hidden',
  height: 0,
  overflow: 'scroll',
  whiteSpace: 'pre'
}
export default function AutosizeInput(props: InputHTMLAttributes<HTMLInputElement>) {
  const originMinWidth = props.style?.minWidth
  const originMaxWidth = props.style?.maxWidth
  const inputRef = useRef<HTMLInputElement>(null)
  const textRef = useRef<HTMLDivElement>(null)
  const [width, setWidth] = useState(1)
  const [refStyle, setRefStyle] = useState({})
  useEffect(() => {
    const s = getComputedStyle(inputRef.current!)
    setRefStyle({
      fontSize: s.fontSize,
      fontFamily: s.fontFamily,
      fontWeight: s.fontWeight,
      fontStyle: s.fontStyle,
      letterSpacing: s.letterSpacing,
      textTransform: s.textTransform
    })
  }, [props.className, props.style])
  useEffect(() => {
    setWidth(textRef.current?.clientWidth || 1)
  }, [props.value, refStyle])
  const textStyle = {...refStyle, ...sizerStyle, display: 'inline-block'}
  if (originMinWidth) textStyle.minWidth = originMinWidth
  if (originMaxWidth) textStyle.maxWidth = originMaxWidth
  return <>
    <input ref={inputRef} {...props} style={{...props.style, width: width + 'px'}}/>
    <div ref={textRef} style={textStyle}>
      {props.placeholder}
      <br/>
      {props.value}
    </div>
  </>
}
import React from 'react'
import ReactDOM from 'react-dom/client'
import AutosizeInput from './AutosizeInput'

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
  <React.StrictMode>
    <AutosizeInput
      style={{minWidth: '50px', maxWidth: '100px'}}
      placeholder="Hello"/>
  </React.StrictMode>
)

0
投票

好吧,我花了一段时间才弄清楚。 我在resume.io编辑器上找到了类似的组件(恢复标题输入) 研究代码后,我发现我们可以在输入上使用父 div 并使输入绝对定位。与此同时,在父 div 内创建另一个段落(只是为了缩放 div),这里有一些代码可以帮助

const AutoSizeInput = () => {
   const [text, setText] = useState("Default Text"); // text
   
   return (
     <div className="relative h-8 max-w-full">
       <input 
          value={text}
          onChange={(e)=>setText(e.target.value)}
          className="absolute top-0 left-0 w-full h-full"
       />
       <p className="opacity-0 invisible whitespace-pre">{text}</p>
     </div>
    )
}

export default AutoSizeInput

我们在这里做的是:

  1. 使p和输入内容相同(包括带有whitespace-pre的空格)
  2. 隐藏 p 标签(它只是为了扩展父 div 的宽度)
  3. 输入是绝对的,因此它将缩放到其父宽度
  4. 此外,您可以为父级 div 指定最小宽度

另外,我在这里使用的是 TailwindCSS,但是你可以按照你想要的方式进行操作。 希望您发现这个解决方案有用

© www.soinside.com 2019 - 2024. All rights reserved.