简体   繁体   English

如何在样式组件中 select 父组件变体?

[英]How to select parent components variant in styled components?

In styled-components we can add contextual styles using component selector pattern .styled-components中,我们可以使用组件选择器模式添加上下文 styles。 But how do we select specific parents variants to contextually style the child component?但是我们如何 select 特定的父变体以上下文样式设置子组件? For example, we have three components here, Child , NoteWrapper , and Note .例如,我们这里有三个组件, ChildNoteWrapperNote

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>
  )
}

`

With plain CSS we could do something like this使用普通的 CSS 我们可以做这样的事情


.child.editing .note-wrapper.compact .note {
  /* Contextual styles here */
}

I know I can easily use the editing and compact variables and pass it to the Note component.我知道我可以轻松地使用editingcompact变量并将其传递给Note组件。 However, it would be difficult to do so if components are highly nested.但是,如果组件高度嵌套,则很难做到这一点。

My question is how do I style Note when Child is editing and NoteWrapper is compact in styled-components selector pattern?我的问题是当Child正在editing并且NoteWrapperstyled-components选择器模式中compact时如何设置Note样式?

I don't think we can do something like this in styled-components in some way?我认为我们不能以某种方式在styled-components中做这样的事情吗? Can we?我们可以吗?

const Note = styled.input`
 ${Child.editingClass} ${NoteWrapper.compactClass} & {
  /* The contextual styles here*/
 }
`

As far as I know, you can't access editing or compact , since they're props and aren't "propagated" in CSS.据我所知,您无法访问 editor 或compact ,因为它们是道具并且不会在editing中“传播”。 But you can achieve the same result using either classes or data attributes.但是您可以使用类或数据属性来获得相同的结果。

Here's how I'd do it:这是我的做法:

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;
  }

`

Essentially, styled-components needs to produce valid CSS at the end of the day.本质上,styled-components 需要在一天结束时生成有效的 CSS。 ${Child} will be replaced by the custom-generated classname, like .sc-abc123 . ${Child}将被自定义生成的类名替换,例如.sc-abc123 And so the end result is .sc-abc123[data-editing="true"] , which is totally-valid CSS.所以最终结果是.sc-abc123[data-editing="true"] ,这是完全有效的 CSS。

You could also use classes, which looks a bit tidier:您还可以使用看起来更整洁的类:

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;
  }

`

I prefer to use data-attributes because it's clear that they're used for logical purposes, and not because editing is a CSS class with a bunch of styles.我更喜欢使用数据属性,因为很明显它们用于逻辑目的,而不是因为editing是 CSS class 和一堆 styles。 But that's a subjective preference, they both work equally well in terms of objective functionality:)但这是一种主观偏好,它们在客观功能方面都同样有效:)

I think it can be solved without the & character我认为它可以在没有&字符的情况下解决

const Note = styled.input`
 ${Child.editingClass} ${NoteWrapper.compactClass} {
  /* The contextual styles here*/
 }
`

You could also pass the props to the Note component itself and do a similar logic check.您还可以将 props 传递给Note组件本身并进行类似的逻辑检查。

<Note
  compactEdit={editing && compact}
/>

const Note = styled.div`
  ${props =>
    props.compactEdit
      ? css`color: red;`
      : css`color: blue;`
    };
`;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM