是否可以选择一种类型的所有反应组件,而不必为每个组件分配一个类?

时间:2018-09-20 11:41:54

标签: javascript reactjs jss

我在这里有一个游乐场: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设置样式-我不想查看组件定义的内部以查找其顶级元素是什么。

我该怎么做?像& SomeOtherElement之类的东西。

此方法的实际应用是,在某些地方我想SomeOtherElement显示block,而在其他地方inline-block

3 个答案:

答案 0 :(得分:4)

我将扩展SomeOtherThing组件以接受className并将其添加到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"
  }
};

答案 1 :(得分:0)

非常简单,在您的someThing CSS代码中,选择类名为p的{​​{1}}元素,并在顶部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
    }
  }
};

CodeSandBox

此方法的工作方式是,通过为const SomeOtherThing = ({ classes, children }) => { return ( <p className={classes.root}> I'm another thing {children} </p> ); }; 提供任何jss类,它将把dom元素呈现为类似以下内容:

SomeOtherThing

<p class="SomeOtherThing-root-0-1-2"> I'm another thing I have some children </p> ] attribute selector匹配的

您应注意,该选择器也将适用于任何更深层的嵌套[class*='SomeOtherThing'

答案 2 :(得分:-1)

CSS的“层叠”方面的一个问题是它破坏了React的组件模型。但是在React中,您始终可以创建一个包装器或高阶组件,该组件将返回另一个带有一些预定义道具的组件,就像工厂函数一样:

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