样式化组件中的样式化嵌套组件

IT技术 javascript reactjs styled-components css-in-js
2021-05-03 15:13:25

我使用样式化组件在 React 中创建了一个下拉组件。以下是该组件的简化轮廓:

const Dropdown = (
    <DropdownBase>
      <Trigger>
        {title}
      </Trigger>
      <Submenu>
        {children}
      </Submenu>
    </DropdownBase>
  )

const DropdownBase = styled.div`
  /* Default Styles */
`

const Trigger = styled(Link)`
  /* Default Styles */
`

const Submenu = styled.div`
  /* Default Styles */
`

现在,当我导入和使用组件时,我希望能够覆盖嵌套组件的默认样式(即DropdownBaseTriggerSubmenu)。我希望能够使用样式化组件覆盖这些默认样式。问题是,我不导入那些嵌套组件——我只导入Dropdown组件——像这样:

import { Dropdown } from '../path/to/dropdown'

<Dropdown />

所以我想知道,当我使用 Styled Components 导入父组件时,如何覆盖这些嵌套组件?

4个回答

最好的方法是从 Dropdown 组件中导出 DropdownBase、Trigger 和 Submenu,然后将它们与 Dropdown 一起导入并像这样覆盖它:

import { Dropdown, DropdownBase, Trigger, Submenu } from '../path/to/dropdown'
import styled from 'styled-components'

const MyComponent = () => {
  return <StyledDropdown />
}

const StyledDropdown = styled(Dropdown)`
  ${DropdownBase} {
    // custom styles
  }

  ${Trigger} {
    // custom styles
  }

  ${Submenu} {
    // custom styles
  }
`

这很有效,因为它针对特定的子样式组件。

或者,您可以根据它们的标签或子顺序来定位它们,但如果您更新 Dropdown 组件,这可能会失败。

这个怎么样:

const Dropdown = (
    <DropdownBase className={dropdownBaseClassName}>
      <Trigger className={triggerClassName}>
        {title}
      </Trigger>
      <Submenu className={submenuClassName}>
        {children}
      </Submenu>
    </DropdownBase>
  )
import { Dropdown } from '../path/to/dropdown'

<StyledDropdown />

const StyledDropdown = styled(Dropdown).attrs({ dropdownBaseClassName:..., triggerClassName:..., submenuClassName:... })`
.${dropdownBaseClassName} {
// styles
}
.${triggerClassName} {
// styles
}
.${submenuClassName} {
// styles
}

通过@Appel21 扩展答案,我会使用点符号来做这样的事情:

import styled from 'styled-components'

export const Dropdown = () => (
    <DropdownBase>
      <Trigger>
        {title}
      </Trigger>
      <Submenu>
        {children}
      </Submenu>
    </DropdownBase>
  )

const DropdownBase = styled.div`
  /* Default Styles */
`

const Trigger = styled(Link)`
  /* Default Styles */
`

const Submenu = styled.div`
  /* Default Styles */
`

Dropdown.base = DropdownBase;
Dropdown.trigger = Trigger;
Dropdown.subMenu = Submenu;

然后使用它:

import { Dropdown } from '../path/to/dropdown' 
import styled from 'styled-components'
    
const MyComponent = () => {
  return <StyledDropdown />
}

const StyledDropdown = styled(Dropdown)`
  ${Dropdown.base} {
    // custom styles
  }

  ${Dropdown.trigger} {
    // custom styles
  }

  ${Dropdown.submenu} {
    // custom styles
  }
`

通过这种方式,您只需导出一个组件,并且您可以自动完成子组件,完全知道您可以设置哪些子组件的样式:)

看起来主题就是你想要的。

import { render } from "react-dom"
import { ThemeProvider } from "styled-components"

const Dropdown = (
    <DropdownBase>
      <Trigger>
        {title}
      </Trigger>
      <Submenu>
        {children}
      </Submenu>
    </DropdownBase>
  )

const defaultTheme = {color:'black'}
const specificTheme = {color:'red'}

const DropdownBase = styled.div`
  /* Default Styles */
  color:${props=>props.theme.color};
`

const Trigger = styled(Link)`
/* Default Styles */
color:${props=>props.theme.color};
`

const Submenu = styled.div`
  /* Default Styles */
  color:${props=>props.theme.color};
`

render(<ThemeProvider theme={defaultTheme}>
    <div>
        <Dropdown>Your default dropdown</Dropdown>
        <div>
            Your hierarchy
            <ThemeProvider theme={specificTheme}>
                <Dropdown>Your custom dropdown</Dropdown>
            </ThemeProvider>
        </div>
    </div>
</ThemeProvider>)