在 styled-components 子组件的输入焦点上设置父组件样式
Style parent component on input focus of child component in styled-components
我在 React 中使用 refs 或事件处理程序看到了一些解决这个问题的繁琐方法。我想知道在 styled-components 中是否有解决方案。
下面的代码显然不正确。当我的输入子组件具有焦点时,我试图找出设置父组件样式的最简单方法。这可能使用样式组件吗?
解决此问题的最佳方法是什么,特别是考虑到样式化组件,即使这意味着依赖上述 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';
}
`;
// 更新 2022:
您可以使用 :focus-within
(感谢您弄清楚@hoodsy)
div:focus-within {
background: #444;
}
<div>
<input type="text" />
</div>
//原答案(支持IE和Edge):
遗憾的是,无法选择 parent,只能根据 child 的纯 CSS/styled-components 状态。虽然它是 CSS4 中的工作草案,但目前没有浏览器支持它。 More about this here.
我通常向输入字段添加一个 onFocus
和 onBlur
属性,然后触发状态更改。在您的情况下,您有一个无状态组件。因此,您可以使用 innerRef
在 parent 中添加或删除 class。但我猜你已经找到了这个解决方案。不过我也会 post :
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
转换为 class,这样您就可以使用状态:
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>
这样您就可以更好地控制您的组件,并且可以更轻松地决定将 focus/blur 状态传递给其他元素。
查看 :focus-within
!我想这正是您要找的。
https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-within
@hoodsy 谢谢,它就像我在父 div 上使用的魅力一样工作,当输入聚焦时改变标签的颜色。
&:focus-within label{
color: blue;
}
我在 React 中使用 refs 或事件处理程序看到了一些解决这个问题的繁琐方法。我想知道在 styled-components 中是否有解决方案。
下面的代码显然不正确。当我的输入子组件具有焦点时,我试图找出设置父组件样式的最简单方法。这可能使用样式组件吗?
解决此问题的最佳方法是什么,特别是考虑到样式化组件,即使这意味着依赖上述 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';
}
`;
// 更新 2022:
您可以使用 :focus-within
(感谢您弄清楚@hoodsy)
div:focus-within {
background: #444;
}
<div>
<input type="text" />
</div>
//原答案(支持IE和Edge):
遗憾的是,无法选择 parent,只能根据 child 的纯 CSS/styled-components 状态。虽然它是 CSS4 中的工作草案,但目前没有浏览器支持它。 More about this here.
我通常向输入字段添加一个 onFocus
和 onBlur
属性,然后触发状态更改。在您的情况下,您有一个无状态组件。因此,您可以使用 innerRef
在 parent 中添加或删除 class。但我猜你已经找到了这个解决方案。不过我也会 post :
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
转换为 class,这样您就可以使用状态:
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>
这样您就可以更好地控制您的组件,并且可以更轻松地决定将 focus/blur 状态传递给其他元素。
查看 :focus-within
!我想这正是您要找的。
https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-within
@hoodsy 谢谢,它就像我在父 div 上使用的魅力一样工作,当输入聚焦时改变标签的颜色。
&:focus-within label{
color: blue;
}