我想要实现的是一个textarea,它以单行开头,但最多会增长到4行,此时如果用户继续输入则会开始滚动。我有一个部分解决方案有点工作,它会增长,然后在达到最大值时停止,但如果你删除文本它不会像我想要的那样缩小。
这是我到目前为止所做的。
export class foo extends React.Component {
constructor(props) {
super(props);
this.state = {
textareaHeight: 38
};
}
handleKeyUp(evt) {
// Max: 75px Min: 38px
let newHeight = Math.max(Math.min(evt.target.scrollHeight + 2, 75), 38);
if (newHeight !== this.state.textareaHeight) {
this.setState({
textareaHeight: newHeight
});
}
}
render() {
let textareaStyle = { height: this.state.textareaHeight };
return (
<div>
<textarea onKeyUp={this.handleKeyUp.bind(this)} style={textareaStyle}/>
</div>
);
}
}
显然,当scrollHeight
设置为更大时,问题height
不会缩减。有关如何修复此问题的任何建议,如果文本被删除,它也会缩减吗?
答案 0 :(得分:12)
您可以{/ 3}}使用
import React, { Component } from 'react';
import autosize from 'autosize';
class App extends Component {
componentDidMount(){
this.textarea.focus();
autosize(this.textarea);
}
render(){
const style = {
maxHeight:'75px',
minHeight:'38px',
resize:'none',
padding:'9px',
boxSizing:'border-box',
fontSize:'15px'};
return (
<div>Textarea autosize <br/><br/>
<textarea
style={style}
ref={c=>this.textarea=c}
placeholder="type some text"
rows={1} defaultValue=""/>
</div>
);
}
}
或者您更喜欢反应模块LIVE DEMO
答案 1 :(得分:5)
只需使用Traceback (most recent call last):
File "program.py", line 24, in <module>
answer = format_days(['Mon', 'Wed', 'Fri'])
File "program.py", line 14, in format_days
days = days.replace(i,REPLACEMENTS[i])
AttributeError: 'list' object has no attribute 'replace'
钩子,它将在渲染器中拾取高度:
useEffect
答案 2 :(得分:2)
使用钩子“ useRef()”真的很简单。
css:
.text-area {
resize: none;
overflow: hidden;
min-height: 30px;
}
反应对象:
export default () => {
const textRef = useRef<any>();
const onChangeHandler = function(e: SyntheticEvent) {
const target = e.target as HTMLTextAreaElement;
textRef.current.style.height = "30px";
textRef.current.style.height = `${target.scrollHeight}px`;
};
return (
<div>
<textarea
ref={textRef}
onChange={onChangeHandler}
className="text-area"
/>
</div>
);
};
答案 3 :(得分:1)
另一种简单的方法(无附加包)
export class foo extends React.Component {
handleKeyDown(e) {
e.target.style.height = 'inherit';
e.target.style.height = `${e.target.scrollHeight}px`;
// In case you have a limitation
// e.target.style.height = `${Math.min(e.target.scrollHeight, limit)}px`;
}
render() {
return <textarea onKeyDown={this.handleKeyDown} />;
}
}
删除文本和文本区域时不会缩回的问题是因为忘记设置此行
e.target.style.height = 'inherit';
考虑使用onKeyDown,因为它适用于所有键,而其他键可能不起作用(w3schools)
如果您有padding
或border
中的top
或bottom
。(reference)
handleKeyDown(e) {
// Reset field height
e.target.style.height = 'inherit';
// Get the computed styles for the element
const computed = window.getComputedStyle(e.target);
// Calculate the height
const height = parseInt(computed.getPropertyValue('border-top-width'), 10)
+ parseInt(computed.getPropertyValue('padding-top'), 10)
+ e.target.scrollHeight
+ parseInt(computed.getPropertyValue('padding-bottom'), 10)
+ parseInt(computed.getPropertyValue('border-bottom-width'), 10);
e.target.style.height = `${height}px`;
}
我希望这会有所帮助。
答案 4 :(得分:1)
您甚至可以使用react refs做到这一点。设置对元素的引用
<textarea ref={this.textAreaRef}></textarea> // after react 16.3
<textarea ref={textAreaRef=>this.textAreaRef = textAreaRef}></textarea> // before react 16.3
并根据需要更新componentDidMount
或componentDidUpdate
上的高度。与
if (this.textAreaRef) this.textAreaRef.style.height = this.textAreaRef.scrollHeight + "px";
答案 5 :(得分:0)
我喜欢使用this.yourRef.current.offsetHeight。由于这是一个文本区域,因此它不会像height:min-content
那样对<div style={{height:"min-content"}}>{this.state.message}</div>
做出响应。因此,我不使用
uponResize = () => {
clearTimeout(this.timeout);
this.timeout = setTimeout(
this.getHeightOfText.current &&
this.setState({
heightOfText: this.getHeightOfText.current.offsetHeight
}),
20
);
};
componentDidMount = () => {
window.addEventListener('resize', this.uponResize, /*true*/)
}
componentWillUnmount = () => {
window.removeEventListener('resize', this.uponResize)
}
而是使用
componentDidUpdate = () => {
if(this.state.lastMessage!==this.state.message){
this.setState({
lastMessage:this.state.message,
height:this.yourRef.current.offsetHeight
})
}
}
在隐藏的div上
<div
ref={this.yourRef}
style={{
height:this.state.height,
width:"100%",
opacity:0,
zIndex:-1,
whiteSpace: "pre-line"
})
>
{this.state.message}
</div>
答案 6 :(得分:0)
运行此代码它有效...
$string = trim(preg_replace('/\s\s+/', ' ', $string));
答案 7 :(得分:0)
实际上你可以用 useState
和 useEffect
function CustomTextarea({minRows}) {
const [rows, setRows] = React.useState(minRows);
const [value, setValue] = React.useState("");
React.useEffect(() => {
const rowlen = value.split("\n");
if (rowlen.length > minRows) {
setRows(rowlen.length);
}
}, [value]);
return (
<textarea rows={rows} onChange={(text) => setValue(text.target.value)} />
);
}
用途
<CustomTextarea minRows={10} />