如何 select 样式组件中的父组件变体?
How to select parent components variant in styled components?
在 styled-components
中,我们可以使用 component selector pattern 添加上下文样式。但是我们如何 select 特定的父变体来根据上下文设置子组件的样式?例如,我们这里有三个组件,Child
、NoteWrapper
和 Note
.
const Child = styled.div<{ editing?: boolean }>`
${props => props.editing && css`some styles`}
`
const NoteWrapper = styled.div<{ compact?: boolean }>`
${props => props.compact && css`some styles`}
`
const Note = styled.input`
/* How do I style this when Child is editing and NoteWrapper is compact */
`
const App = () => {
return (
<Child editing>
<NoteWrapper compact>
<Note/>
</NoteWrapper>
</Child>
)
}
`
使用普通 CSS 我们可以做这样的事情
.child.editing .note-wrapper.compact .note {
/* Contextual styles here */
}
我知道我可以轻松使用 editing
和 compact
变量并将其传递给 Note
组件。但是,如果组件高度嵌套,就很难做到。
我的问题是当 Child
是 editing
并且 NoteWrapper
是 compact
时 Note
在 styled-components
select或模式?
我认为我们不能以某种方式在 styled-components
中做这样的事情?我们可以吗?
const Note = styled.input`
${Child.editingClass} ${NoteWrapper.compactClass} & {
/* The contextual styles here*/
}
`
据我所知,您无法访问 editing
或 compact
,因为它们是道具,不会在 CSS 中“传播”。但是您可以使用 classes 或数据属性获得相同的结果。
这是我的做法:
const App = () => {
return (
<Child data-editing={true}>
<NoteWrapper data-compact={true}>
<Note/>
</NoteWrapper>
</Child>
)
}
const Child = styled.div`
`
const NoteWrapper = styled.div`
`
const Note = styled.input`
${Child}[data-editing="true"] ${NoteWrapper}[data-compact="true"] & {
/*
Only applied when Child is editing and NoteWrapper is compact
*/
color: red;
}
`
本质上,styled-components 需要在一天结束时产生有效的 CSS。 ${Child}
将替换为自定义生成的 class 名称,例如 .sc-abc123
。所以最终结果是 .sc-abc123[data-editing="true"]
,这是完全有效的 CSS.
你也可以使用 classes,它看起来更简洁:
const App = () => {
return (
<Child className="editing">
<NoteWrapper className="compact">
<Note/>
</NoteWrapper>
</Child>
)
}
const Child = styled.div`
`
const NoteWrapper = styled.div`
`
const Note = styled.input`
${Child}.editing ${NoteWrapper}.compact & {
/*
Only applied when Child is editing and NoteWrapper is compact
*/
color: red;
}
`
我更喜欢使用数据属性,因为很明显它们用于逻辑目的,而不是因为 editing
是 CSS class 和一堆样式。但这是一种主观偏好,它们在 objective 功能方面都同样出色:)
您也可以将道具传递给 Note
组件本身并进行类似的逻辑检查。
<Note
compactEdit={editing && compact}
/>
const Note = styled.div`
${props =>
props.compactEdit
? css`color: red;`
: css`color: blue;`
};
`;
在 styled-components
中,我们可以使用 component selector pattern 添加上下文样式。但是我们如何 select 特定的父变体来根据上下文设置子组件的样式?例如,我们这里有三个组件,Child
、NoteWrapper
和 Note
.
const Child = styled.div<{ editing?: boolean }>`
${props => props.editing && css`some styles`}
`
const NoteWrapper = styled.div<{ compact?: boolean }>`
${props => props.compact && css`some styles`}
`
const Note = styled.input`
/* How do I style this when Child is editing and NoteWrapper is compact */
`
const App = () => {
return (
<Child editing>
<NoteWrapper compact>
<Note/>
</NoteWrapper>
</Child>
)
}
`
使用普通 CSS 我们可以做这样的事情
.child.editing .note-wrapper.compact .note {
/* Contextual styles here */
}
我知道我可以轻松使用 editing
和 compact
变量并将其传递给 Note
组件。但是,如果组件高度嵌套,就很难做到。
我的问题是当 Child
是 editing
并且 NoteWrapper
是 compact
时 Note
在 styled-components
select或模式?
我认为我们不能以某种方式在 styled-components
中做这样的事情?我们可以吗?
const Note = styled.input`
${Child.editingClass} ${NoteWrapper.compactClass} & {
/* The contextual styles here*/
}
`
据我所知,您无法访问 editing
或 compact
,因为它们是道具,不会在 CSS 中“传播”。但是您可以使用 classes 或数据属性获得相同的结果。
这是我的做法:
const App = () => {
return (
<Child data-editing={true}>
<NoteWrapper data-compact={true}>
<Note/>
</NoteWrapper>
</Child>
)
}
const Child = styled.div`
`
const NoteWrapper = styled.div`
`
const Note = styled.input`
${Child}[data-editing="true"] ${NoteWrapper}[data-compact="true"] & {
/*
Only applied when Child is editing and NoteWrapper is compact
*/
color: red;
}
`
本质上,styled-components 需要在一天结束时产生有效的 CSS。 ${Child}
将替换为自定义生成的 class 名称,例如 .sc-abc123
。所以最终结果是 .sc-abc123[data-editing="true"]
,这是完全有效的 CSS.
你也可以使用 classes,它看起来更简洁:
const App = () => {
return (
<Child className="editing">
<NoteWrapper className="compact">
<Note/>
</NoteWrapper>
</Child>
)
}
const Child = styled.div`
`
const NoteWrapper = styled.div`
`
const Note = styled.input`
${Child}.editing ${NoteWrapper}.compact & {
/*
Only applied when Child is editing and NoteWrapper is compact
*/
color: red;
}
`
我更喜欢使用数据属性,因为很明显它们用于逻辑目的,而不是因为 editing
是 CSS class 和一堆样式。但这是一种主观偏好,它们在 objective 功能方面都同样出色:)
您也可以将道具传递给 Note
组件本身并进行类似的逻辑检查。
<Note
compactEdit={editing && compact}
/>
const Note = styled.div`
${props =>
props.compactEdit
? css`color: red;`
: css`color: blue;`
};
`;