我需要一个具有最小宽度和最大宽度的输入,它将根据其内容增大和缩小
你必须有状态。它可以作为参数传递(提升状态,当状态位于上层时)或直接在组件中
然后只需使用输入状态的长度
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>
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>
)
好吧,我花了一段时间才弄清楚。 我在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
我们在这里做的是:
另外,我在这里使用的是 TailwindCSS,但是你可以按照你想要的方式进行操作。 希望您发现这个解决方案有用