使用 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 和组件(在您的情况下,嵌套 div
、input
、a
)。
要使此方法起作用,您的根 DOM 必须具有可以从外部配置的 className
。这就是为什么 styled-components
期望根 DOM 具有定义 ${this.props.className}
作为其 className
属性的值。如果你的组件缺少这个,styled-components
将无法创建一个新的命名空间,它可以使用它来应用特定于它的样式。
因此,为了让您的技术发挥作用,您必须将 ${this.props.className}
指定为 className
在 div
的根部定义的道具的值之一14=].
如果您无权访问SearchBar
,您可以用另一个组件包装它。这个过程的开销是,你必须使用额外的 DOM 级别
目前在版本 4 中,您可以像
一样简单地做到这一点
const Input = styled.input`
border:2px solid red !important;
`;
它将呈现为带有 SC 类名的本机输入
我无法让我的样式化组件更改包含在 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 和组件(在您的情况下,嵌套 div
、input
、a
)。
要使此方法起作用,您的根 DOM 必须具有可以从外部配置的 className
。这就是为什么 styled-components
期望根 DOM 具有定义 ${this.props.className}
作为其 className
属性的值。如果你的组件缺少这个,styled-components
将无法创建一个新的命名空间,它可以使用它来应用特定于它的样式。
因此,为了让您的技术发挥作用,您必须将 ${this.props.className}
指定为 className
在 div
的根部定义的道具的值之一14=].
如果您无权访问SearchBar
,您可以用另一个组件包装它。这个过程的开销是,你必须使用额外的 DOM 级别
目前在版本 4 中,您可以像
一样简单地做到这一点const Input = styled.input`
border:2px solid red !important;
`;
它将呈现为带有 SC 类名的本机输入