1

这两个文本区域只是略有不同,我不明白为什么第二个不起作用。

这是 Codepen

const StyledTextarea = styled.textarea`
  display: block;
  font-size: 20px;
  line-height: 40px;
  min-height: 120px;
  overflow: hidden;
  padding: 0 7px;
  margin: 0 0 30px;
  resize: none;
  width: 500px;
`;

const Label = styled.span`
  color: ${props => props.green ? '#00BB00' : 'red'};
  font-size: 1.5em;
`;

const App = () => {
  return(
    <div>
      <Label green>✅ Textarea1 - Working </Label>
      <Textarea1 />
      <Label>❌ Textarea2 - Not working </Label>
      <Textarea2 />
    </div>
  )
}

class Textarea1 extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
          value: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Assumenda voluptas deleniti at, molestias in amet dolore voluptatem atque, modi minus ipsam dignissimos...',
          scrollHeight: 0,
        }
    }

    onChange(e) {
      const t = e.target;
      t.style.height = 'auto';
      t.style.height = `${t.scrollHeight}px`;
      this.setState({value: t.value});
    }

    render() {
        return (
            <StyledTextarea
              value={this.state.value}
              onChange={this.onChange.bind(this)}
            />
        );
    }
}

class Textarea2 extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
          value: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Assumenda voluptas deleniti at, molestias in amet dolore voluptatem atque, modi minus ipsam dignissimos...',
          scrollHeight: 0,
        }
    }

    onChange(e) {
      const bugger = e.target;
       console.log('style.height before it is set to auto: ', bugger.style.height)
      bugger.style.height = 'auto';
       console.log('style.height after it is set to auto (obviously): ', bugger.style.height)
       console.log('.scroll height: ', bugger.scrollHeight);
      this.setState({
        scrollHeight: bugger.scrollHeight,
        value: bugger.value
      });
    }

    render() {
        return (
            <StyledTextarea
              style={{height: `${this.state.scrollHeight}px`}}
              value={this.state.value}
              onChange={this.onChange.bind(this)}
            />
        );
    }
}

两者都使用类似的方式来保持它们的高度与内容的高度同步。style.height然而,第二个,我认为应该用新的(来自更新的状态)重新渲染,不应用新的样式。在控制台中查看有问题的值 - style.height 即使在分配新值之后仍保持“自动”。但是,如果您只按 Enter 和 Backspace ,它就可以工作。

什么是我不明白的?

4

1 回答 1

2

这是一个棘手的问题,与您在 React 中使用styled-components库有关,而不是与您的 React 代码本身有关。在您的渲染中,您Textarea1正在创建一个StyledTextarea传入的 style 道具。不幸的是,使用 styled-components 创建的组件会忽略此道具。

当使用带有 react 的 styled-components 时,你应该将你的 props 拉出来并将它们应用到你的 css 中,如下面的代码笔所示:

const styled = styled.default;

const Button = styled.button`
  background: red;
  border-radius: 8px;
  color: white;
  height: ${props => props.small ? 40 : 60}px;
  width: ${props => props.small ? 60 : 120}px;
`;

class Application extends React.Component {
  render() {
    return (
      <div>
        <Button small>Click Me</Button>
        <Button large>Click Me</Button>
      </div>
    )
  }
}

ReactDOM.render(<Application />, document.getElementById('content'));

要解决您的问题,您必须将您的 style.height 道具拉出StyledTextArea并将您的高度重置''为 Textarea2.onChange 的末尾。这是您进行这些更改的代码。请注意,这会破坏 Textarea1 中的大小调整:

const styled = styled.default;

const StyledTextarea = styled.textarea`
  display: block;
  font-family: PT Sans;
  font-size: 20px;
  line-height: 40px;
  min-height: 120px;
  overflow: hidden;
  padding: 0 7px;
  margin: 0 0 30px;
  resize: none;
  width: 500px;
  // one update here
  height: ${props => (props.style && props.style.height) ? props.style.height + 'px' : '0px'};
`;

const Label = styled.span`
  color: ${props => props.green ? '#00BB00' : 'red'};
  font-size: 1.5em;
`;

const App = () => {
  return(
    <div>
      <Label green>✅ Textarea1 - Working </Label>
      <Textarea1 />
      <Label>❌ Textarea2 - Not working </Label>
      <Textarea2 />
    </div>
  )
}

class Textarea1 extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
          value: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Assumenda voluptas deleniti at, molestias in amet dolore voluptatem atque, modi minus ipsam dignissimos...',
          scrollHeight: 0,
        }
    }

    onChange(e) {
      const t = e.target;
      t.style.height = 'auto';
      t.style.height = `${t.scrollHeight}px`;
      this.setState({value: t.value});
    }

    render() {
        return (
            <StyledTextarea
              value={this.state.value}
              onChange={this.onChange.bind(this)}
            />
        );
    }
}

class Textarea2 extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
          value: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Assumenda voluptas deleniti at, molestias in amet dolore voluptatem atque, modi minus ipsam dignissimos...',
          scrollHeight: 0,
        }
    }

    onChange(e) {
      const bugger = e.target;
       console.log('style.height before it is set to auto: ', bugger.style.height)
      bugger.style.height = 'auto';
       console.log('style.height after it is set to auto (obviously): ', bugger.style.height)
       console.log('.scroll height: ', bugger.scrollHeight);
      this.setState({
        scrollHeight: bugger.scrollHeight,
        value: bugger.value
      });
      // another update here
      bugger.style.height = '';
    }

    render() {
      console.log(this.state.scrollHeight);
        return (
            <StyledTextarea
              style={{height: this.state.scrollHeight}}
              value={this.state.value}
              onChange={this.onChange.bind(this)}
            />
        );
    }
}

ReactDOM.render(<App />, document.getElementById('root'));

最后一点,您使用的第二种方法绝对是更可取的方法!通过处理程序而不是渲染方法修改组件样式并不理想。

于 2017-06-25T02:24:25.993 回答