使用 styled-components 定位原生 dom 元素 <input>...</input>

Target native dom element <input>...</input> with styled-components

我无法让我的样式化组件更改包含在 React 组件中的 <input />。在 Dev Tools 中,我可以在此处看到我试图覆盖的样式:

.ui.input input {...}

我认为包装组件需要将 className 传递给输入,即

<input className = {this.props.className} ..> ... </input>

但不管有没有它,我都无法获得要覆盖的样式。我将在下面提供一些片段。

//styled component
const StyledSearch = styled(Searchbar)`
  &.ui.input input{
    border: 0px !important;
  }
`;


class SearchBar extends Component {
...
render() {
const style = {
  display: this.state.showResults ? 'block' : 'none',
  maxHeight: 500,
  overflowY: 'scroll',
};
return (
  <div className="ui search fluid" ref="container">
    <div
      className={`ui icon fluid input ${this.props.loading ? 'loading' : ''}`}>
      <input type="text"
        placeholder={this.props.placeholder}
        onFocus={this.focus}
        className = {this.props.className}
        value={this.props.value}
        onChange={this.props.onChange}/>
      <i className="search icon"></i>
    </div>
    <div
      className="results"
      style={style}>

      {
        this.props.results.map((result, index) => (
            <a
              className="result"
              key={index}
              onClick={this.select.bind(this, result)}>
              <div className="content">
                {
                  result.get('image') ?
                  (
                    <div className="image">
                      <img src={result.get('image')} style={{ maxWidth: 50 }}/>
                    </div>
                  ) : null
                }
                <div className="title">
                  {result.get('title')}
                </div>
                <div className="description">
                  {result.get('description')}
                </div>
              </div>
            </a>
          )
        )
      }
    </div>
  </div>
);}}

据我所知,您需要将使用 styled-components 生成的样式应用到包装器元素。这是由于 .ui.input input 外部样式的特殊性。这意味着我们不能简单地使用新样式来定位 input 元素,因为 .ui.input input 选择器更具体并且具有优先权。这是一个简单的 CSS 示例,展示了 .ui.input input 选择器的特殊性如何优先于 input 样式:

.ui.input input {
  border:2px solid red !important;
}

input {
  border: 0px !important;
}
<div class="ui input">
  <input />
</div>

您的情况也存在同样的问题。在下面的示例中,我创建了一个新的 Wrapper 组件,其样式为:

&.ui.input input {
  border: 0px !important;
  font-size: 24px;
}   

定义就可以了。这针对内部 input 元素,更具体,以覆盖外部样式。

import React from 'react';
import ReactDOM from 'react-dom';
import styled from 'styled-components';

class InputWrapper extends React.Component {

  render() {
     const Wrapper = styled.div`
       &.ui.input input {
         border: 0px !important;
         font-size: 24px;
       }
     `;

    return(
      <Wrapper className="ui input">
        <input type="text" placeholder="Input" />
      </Wrapper>
    )
  }
}


ReactDOM.render(
    <InputWrapper />, 
    document.getElementById("app")
);

这是一个 WebpackBin 示例。

基本上,styled-components 为任何 DOM 或 React 创建一个 新的唯一 class 名称(换句话说,一个新的命名空间)调用 styled 函数的组件。

这意味着,当您使用 styled(SearchBar) 时,styled-components 包装 SearchBar 组件并将唯一的 class 名称附加到其根 DOM。然后它将唯一的 class 名称传递给后代 DOM 和组件(在您的情况下,嵌套 divinputa)。

要使此方法起作用,您的根 DOM 必须具有可以从外部配置的 className。这就是为什么 styled-components 期望根 DOM 具有定义 ${this.props.className} 作为其 className 属性的值。如果你的组件缺少这个,styled-components 将无法创建一个新的命名空间,它可以使用它来应用特定于它的样式。

因此,为了让您的技术发挥作用,您必须将 ${this.props.className} 指定为 classNamediv 的根部定义的道具的值之一14=].

Working Demo

如果您无权访问SearchBar,您可以用另一个组件包装它。这个过程的开销是,你必须使用额外的 DOM 级别

Working Demo

目前在版本 4 中,您可以像

一样简单地做到这一点
const Input = styled.input`
  border:2px solid red !important;
`;

它将呈现为带有 SC 类名的本机输入