【问题标题】:Style parent component on input focus of child component in styled-components样式化组件中子组件输入焦点的样式父组件
【发布时间】:2023-03-26 03:38:01
【问题描述】:

我已经看到了一些针对这个问题的繁重解决方案,在 React 中使用 refs 或事件处理程序。我想知道样式组件中是否有解决方案。

下面的代码显然不正确。当我的输入子组件具有焦点时,我试图找出最简单的方法来设置我的父组件的样式。这可以使用样式组件吗?

最好的方法是什么,特别是考虑到样式组件,即使这意味着依赖上面提到的 React 方法之一?

const Parent = () => (
  <ParentDiv>
    <Input/>
  </ParentDiv>
);


const ParentDiv = styled.div`
  background: '#FFFFFF';

  ${Input}:focus & {
    background: '#444444';
  }
`;

const Input = styled.input`
  color: #2760BC;

  &:focus{
    color: '#000000';
  }
`;

【问题讨论】:

    标签: javascript reactjs styled-components


    【解决方案1】:

    查看:focus-within!我认为这正是您想要的。

    https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-within

    【讨论】:

    【解决方案2】:

    // 2018 年更新:

    如果您不需要 Edge 或 IE 支持,您可以使用 :focus-within(感谢您了解 @hoodsy)

    div:focus-within {
      background: #444;
    }
    <div>
      <input type="text" />
    </div>

    // 原答案(支持 IE 和 Edge)

    遗憾的是,没有办法选择父级,只能基于子级的状态和纯 CSS/样式组件。虽然它是 CSS4 中的工作草案,但目前没有浏览器支持它。 More about this here.

    我通常将onFocusonBlur 属性添加到输入字段,然后触发状态更改。在您的情况下,您有一个无状态组件。因此,您可以使用innerRef 从父级添加或删除一个类。但我想你已经找到了这个解决方案。不过我也会发布它:

    const styled = styled.default;
    
    const changeParent = ( hasFocus, ref ) => {
      // IE11 does not support second argument of toggle, so...
      const method = hasFocus ? 'add' : 'remove';
      ref.parentElement.classList[ method ]( 'has-focus' );
    }
    
    const Parent = () => {
      let inputRef = null;
      
      return (
        <ParentDiv>
          <Input
            innerRef={ dom => inputRef = dom }
            onFocus={ () => changeParent( true, inputRef ) }
            onBlur={ () => changeParent( false, inputRef ) }
          />
        </ParentDiv>
      );
    };
    
    const ParentDiv = styled.div`
      background: #fff;
    
      &.has-focus {
        background: #444;
      }
    `;
    
    const Input = styled.input`
      color: #2760BC;
    
      &:focus{
        color: #000;
      }
    `;
    
    ReactDOM.render( <Parent />, document.getElementById( 'app' ) );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    <script src="https://unpkg.com/styled-components/dist/styled-components.min.js"></script>
    
    <div id="app"></div>

    更严格的方法是将Parent 转换为类,这样您就可以使用状态:

    const styled = styled.default;
    
    class Parent extends React.Component {
      state = {
        hasFocus: false,
      }
      
      setFocus = ( hasFocus ) => {
        this.setState( { hasFocus } );
      }
      
      render() {
        return (
          <ParentDiv hasFocus={ this.state.hasFocus }>
            <Input
              onFocus={ () => this.setFocus( true )  }
              onBlur={ () => this.setFocus( false ) }
            />
          </ParentDiv>
        );
      }
    };
    
    const ParentDiv = styled.div`
      background: ${ props => props.hasFocus ? '#444' : '#fff' };
    
    `;
    
    const Input = styled.input`
      color: #2760BC;
    
      &:focus{
        color: #000;
      }
    `;
    
    ReactDOM.render( <Parent />, document.getElementById( 'app' ) );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    <script src="https://unpkg.com/styled-components/dist/styled-components.min.js"></script>
    
    <div id="app"></div>

    这样您可以更好地控制您的组件,并且可以更轻松地决定将焦点/模糊状态传递给其他元素。

    【讨论】:

      【解决方案3】:

      @hoodsy 谢谢,它就像我在父 div 上使用的魅力一样,可以在输入集中时更改标签的颜色。

           &:focus-within label{
            color: blue;
        }
      

      【讨论】:

        猜你喜欢
        • 2018-12-20
        • 2020-05-23
        • 2019-11-27
        • 1970-01-01
        • 2020-10-27
        • 1970-01-01
        • 2020-09-26
        • 2020-09-22
        • 2018-02-22
        相关资源
        最近更新 更多