我可以选择一种类型的所有react组件,而不为每个组件分配一个类吗?

IT技术 javascript reactjs jss
2021-05-25 16:36:24

我在这里有一个游乐场:https : //codesandbox.io/s/736v9vjzw1

const Something = ({ classes, children, variant }) => {
  return (
    <div className={classes.someThing}>
      <p> I'm some thing </p>

      <SomeOtherThing />

      <SomeOtherThing> I have some children </SomeOtherThing>

      <SomeOtherThing> I have some children </SomeOtherThing>

      <SomeOtherThing> I have some children </SomeOtherThing>
    </div>
  );
};

const styles = {
  someThing: {
    color: "green",
    border: "solid 2px black",
    margin: 30,

    "& $someOtherThing": {
      backgroundColor: "pink" // Doesn't work
    },

    "& p": {
      fontWeight: "bold" //This works but is too broad
    }
  }
};

我在这里有一个情况,我想SomeOtherThing在我的SomeThing.

我可以使用& p选择器来选择p元素 - 但我不喜欢这样。它可以设置p我周围的任何随机s 的样式- 我不想查看组件定义内部来查找它的顶级元素是什么。

我怎样才能做到这一点?类似的东西& SomeOtherElement

这个在现实世界的应用,是在我想要的一些地方和其他地方SomeOtherElement显示blockinline-block

3个回答

我会扩展SomeOtherThing组件以接受 className 并将其添加到divif 中。这也适用于生产设置,其中类名被缩小到例如.t-0-root.

这是一个分叉的游乐场:https : //codesandbox.io/s/zlzx277zzm,展示了如何使用它。

const SomeOtherThing = ({ classes, children, className }) => {
  return (
    <p className={`${classes.someOtherThing} ${className && className}`}>
      I'm another thing {children}
    </p>
  );
};

我很可能会使用该包classnames来有条件地呈现类名而不是字符串插值。

const Something = ({ classes, children, variant }) => {
  return (
    <div className={classes.someThing}>
      <p> I'm some thing </p>

      <SomeOtherThing />

      <SomeOtherThing className={classes.someOtherThing}>
        I have some children
      </SomeOtherThing>

      <SomeOtherThing className={classes.someOtherThing}>
        I have some children
      </SomeOtherThing>

      <SomeOtherThing className={classes.someOtherThing}>
        I have some children
      </SomeOtherThing>
    </div>
  );
};

const styles = {
  someThing: {
    color: "green",
    border: "solid 2px black",
    margin: 30
  },
  someOtherThing: {
    backgroundColor: "pink"
  }
};

就这么简单,在你的someThingCSS 代码中选择pclasssomeOtherThing类名元素,在顶层使用not()CSS 操作p,看下面的代码:

const styles = {
  someThing: {
    color: "green",
    border: "solid 2px black",
    margin: 30,

    "& [class*='SomeOtherThing']": {
      backgroundColor: "pink" // 
    },

    "& :not([class*='SomeOtherThing'])": {
      fontWeight: "bold" // Just for top level p
    }
  }
};

const SomeOtherThing = ({ classes, children }) => {
  return (
    <p className={classes.root}> I'm another thing {children} </p>
  );
};

代码沙盒

它的工作方式是,通过提供SomeOtherThing任何 jss 类,它会将 dom 元素呈现为如下所示:

 <p class="SomeOtherThing-root-0-1-2"> I'm another thing  I have some children  </p>

其中[class*='SomeOtherThing']属性选择器将匹配。

你应该注意到这个选择器也适用于任何更深的嵌套SomeOtherThings。

CSS 的“级联”方面的一个问题是它在某种程度上破坏了 React 的组件模型。但是在 React 中,你总是可以创建一个包装器或高阶组件,它返回另一个带有一些预定义 props 的组件,有点像工厂函数:

const Something = props => {
  return (
    <div className={props.className}>
      // ...
    </div>
  )
}

const SomethingInline = props => {
  return <Something className='display-inline' {...props} />
}

const SomethingBlock = props => {
  return <Something className='display-block' {...props} />
}

const App = () => {
  return (
    <div>
      <SomethingInline />
      <SomethingBlock />
      <SomethingBlock> I have children </SomethingBlock>
    </div>
  )
}

不要使用&选择器来定义您的样式,而是创建一个仅适用于组件的这些特定版本的类。通过这种方式,避免了 CSS 的全局范围,您可以创建这些描述自己样式的声明性组件,但不需要您显式传递类名。