4

我在这里有一个游乐场: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元素——但我不喜欢这样。它会为我周围的任何随机ps 设置样式——而且我不想查看组件定义内部来找到它的顶级元素是什么。

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

这个在现实世界中的应用,是在一些我想要的地方已经SomeOtherElement显示block,而在其他地方inline-block

4

3 回答 3

4

我会扩展SomeOtherThing组件以接受一个类名并将其添加到div如果存在的话。这也适用于生产设置,其中类名被缩小为例如.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"
  }
};
于 2018-10-01T11:22:45.440 回答
0

这很简单,在您的someThingCSS 代码中选择p具有类名的元素并在顶层someOtherThing使用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。

于 2018-10-01T19:37:08.343 回答
-1

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 的全局范围,您可以创建这些描述自己样式的声明性组件,但不需要您显式传递类名。

于 2018-10-03T03:43:54.953 回答