javascript/react动态高度textarea(停在最大值)

jcm*_*tch 10 html javascript css reactjs

我想要实现的是一个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>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

显然问题是scrollHeightheight设置为更大的时候不会缩减.有关如何修复此问题的任何建议,如果文本被删除,它也会缩减吗?

Kok*_*lav 15

您可以使用自动调整大小

现场演示

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>
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

或者如果您更喜欢反应模块https://github.com/andreypopp/react-textarea-autosize


saj*_*jan 10

如果你使用钩子“useRef()”,那就非常简单了。

CSS:

.text-area {
   resize: none;
   overflow: hidden;
   min-height: 30px;
}
Run Code Online (Sandbox Code Playgroud)

反应组件:

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>
  );
};
Run Code Online (Sandbox Code Playgroud)


Tat*_*tsu 9

另一种简单的方法(不带附加包装)

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} />;
  }
}
Run Code Online (Sandbox Code Playgroud)

删除文本和textarea时不会缩回的问题是因为忘记设置此行

e.target.style.height = 'inherit';
Run Code Online (Sandbox Code Playgroud)

考虑使用onKeyDown,因为它适用于所有键,而其他键则可能不适用(w3schools

如果你有paddingbordertopbottom参考

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`;
}
Run Code Online (Sandbox Code Playgroud)

希望对您有所帮助。

  • 当 TextArea 具有初始长文本时,此操作失败 (6认同)

Але*_*лин 7

只需使用useEffect钩子即可在渲染器期间获取高度:

import React, { useEffect, useRef, useState} from "react";
const defaultStyle = {
    display: "block",
    overflow: "hidden",
    resize: "none",
    width: "100%",
    backgroundColor: "mediumSpringGreen"
};

const AutoHeightTextarea = ({ style = defaultStyle, ...etc }) => {
    const textareaRef = useRef(null);
    const [currentValue, setCurrentValue ] = useState("");// you can manage data with it

    useEffect(() => {
        textareaRef.current.style.height = "0px";
        const scrollHeight = textareaRef.current.scrollHeight;
        textareaRef.current.style.height = scrollHeight + "px";
    }, [currentValue]);

    return (
        <textarea
            ref={textareaRef}
            style={style}
            {...etc}
            value={currentValue}

            onChange={e=>{
            setCurrentValue(e.target.value);
            //to do something with value, maybe callback?
            }
        />
    );
};

export default AutoHeightTextarea;
Run Code Online (Sandbox Code Playgroud)


Yas*_*jha 5

你甚至可以用 react refs 来做到这一点。作为将 ref 设置为元素

<textarea ref={this.textAreaRef}></textarea> // after react 16.3
<textarea ref={textAreaRef=>this.textAreaRef = textAreaRef}></textarea> // before react 16.3
Run Code Online (Sandbox Code Playgroud)

和更新的高度componentDidMountcomponentDidUpdate为您的需要。和,

if (this.textAreaRef) this.textAreaRef.style.height = this.textAreaRef.scrollHeight + "px";
Run Code Online (Sandbox Code Playgroud)