6

我有一个关于作文的问题,希望有人能帮助我。我正在使用react-css-modulesSass,我想知道为我们的基本底层组件之一组合事物的最佳方式。

这是我们的组件:

import React, {PropTypes} from 'react'
import cssModules from 'react-css-modules'
import styles from './style.sass'

const Button = ({children = 'Submit', ...props}) => {
  const align = props.align ? `-${props.align}` : ''
  const type = props.type ? `-${props.type}` : ''
  const styleName = `button${type}${align}`

  return (
    <button onClick={props.onClick} {...props} styleName={styleName}>
      {children}
    </button>
  )
}

Button.propTypes = {
  align: PropTypes.string,
  onClick: PropTypes.func.isRequired,
  type: PropTypes.string,
}

export default cssModules(Button, styles)

这是到目前为止的样式表:

@import "~components/styles/variables"

.button
  color: $button-default
  background-color: transparent
  font-family: $font-family
  font-size: $default-font-size
  font-weight: $font-regular
  line-height: $default-button-height
  margin: 0 $pad 0 0
  outline: none
  padding: 0 $pad*2

.left
  float: left

.right
  float: right

.primary
  color: $background-interaction
  background-color: $button-default

.button-left
  composes: button, left

.button-right
  composes: button, right

.button-primary
  composes: button, primary

.button-primary-left
  composes: button, primary, left

.button-primary-right
  composes: button, primary, right

目前来看,还挺痛苦的。我们添加的每个可配置道具都会以指数方式增加我们必须提供的组合类的数量。我们目前可以配置alignand type,并且由于两者都可以为 null 我们有 6 种可能的组合,因此除了 base 之外还要创建 5 个组合类.button。如果我们只添加一个道具,比如一个 boolean bold,我们现在必须添加一大堆新的组合类名:.button-bold, .button-left-bold, .button-right-bold, .button-primary-bold, .button-primary-left-bold, .button-primary-right-bold.

我知道react-css-modules我们可以启用该allowMultiple设置以允许我们指定多个模块以应用于一个元素,但我的理解是这违反了最佳实践。我觉得我们必须在这里遗漏一些东西。我们做错了什么?

4

2 回答 2

7

我认为该示例中可能存在多种问题,这就是为什么它不符合“每个元素一个类”规则的原因。强制执行每个元素一个类规则的原因之一是,我们可以轻松更改元素状态的外观,而无需实际接触元素。(基本上是CSS本身的承诺,终于实现了。)如果你在一个元素上有多个类,在不改变元素的情况下很难控制外观。如果您使用外观(而不是语义)类,则尤其如此。

像“button-primary-left-bold”这样的类有一些语义含义(“button-primary”),但它也有一些布局含义(“left”)和一些文本外观含义(“bold”)。Button 组件可能没有控制自己的布局的业务。请记住,您也可以编写 React 组件!所以你可以有更多类似的东西:

<Left><Button type="primary">Click Me!</Button></Left>

现在 Button 组件的 CSS 模块可以只关心按钮的类型。而且 Button 组件可以在任何地方使用,具有任何布局,而不仅仅是基于浮动的布局。

更好的是,浮动也可以被推入更具语义的组件中。也许是这样的:

<ButtonBar>
  <Button>Cancel</Button>
  <Button type="primary">Save</Button>
</ButtonBar>

ButtonBar 可以有自己的 CSS 模块来进行布局。稍后你可以将这个 janky float 布局换成一个时髦的 flexbox 布局。:-)

您的“粗体”修饰符示例在 Button 组件中肯定没有位置。最好考虑一下为什么有些东西是粗体的,然后为此创建一个组件或语义属性。否则,如果设计要求将那些“粗体”按钮更改为“斜体绿色”按钮,则您必须四处更改一堆元素。

如果你这样做(为语义组件交换视觉/布局类并分解组件和 CSS 模块),你将有更少的“指数增长”。如果您最终确实需要组合多个语义属性,那么说明这些状态仍然有一些价值。一个很好的例子可能是“primary-disabled”。出于几个原因,这比“主要残疾人”要好。首先,很容易查看 CSS 模块并查看列出的显式状态。其次,这些类的用途和关系没有歧义。“主要禁用”实际上是对这些类的有效使用吗?这只有在有人记录使用时才能知道。“禁用”类可能会覆盖“主要”类中的某些内容,意味着存在隐含的排序依赖关系。未来善意的编辑很容易破坏事物,因为这些类之间的关系并不明显。通常情况下,选择隐含的东西来保存一些击键可能会导致细微的错误。支付那一点按键税可以锁定事情,并清楚地表明什么会起作用,什么不会。

另一个可以为您节省一些击键的小点:实际上没有理由使用“button-”前缀。这正是 CSS 模块的用途。改为这样做:

.normal
  color: $button-default
  background-color: transparent
  font-family: $font-family
  font-size: $default-font-size
  font-weight: $font-regular
  line-height: $default-button-height
  margin: 0 $pad 0 0
  outline: none
  padding: 0 $pad*2

.primary
  composes: normal
  color: $background-interaction
  background-color: $button-default

文件名本身本质上是“按钮”前缀。

于 2016-01-18T06:49:29.670 回答
2

我想在这种情况下我会远离撰写并嵌套你的课程。这是我的建议(如果我的 jsx 有点不对,请原谅我):

import React, {PropTypes} from 'react'
import cssModules from 'react-css-modules'
import styles from './style.sass'

const Button = ({children = 'Submit', ...props}) => {
  const align = props.align ? `${props.align}` : ''
  const type = props.type ? `${props.type}` : ''
  const styleName = `button ${type} ${align}`

  return (
    <button onClick={props.onClick} {...props} styleName={styleName}>
      {children}
    </button>
  )
}

Button.propTypes = {
  align: PropTypes.string,
  onClick: PropTypes.func.isRequired,
  type: PropTypes.string,
}

export default cssModules(Button, styles)

和 SASS:

@import "~components/styles/variables"

.button
  color: $button-default
  background-color: transparent
  font-family: $font-family
  font-size: $default-font-size
  font-weight: $font-regular
  line-height: $default-button-height
  margin: 0 $pad 0 0
  outline: none
  padding: 0 $pad*2

  &.left
    float: left

  &.right
    float: right

  &.primary
    color: $background-interaction
    background-color: $button-default

完全承认“left”和“primary”可能与您应用程序中的其他类名冲突。因此,提出一些更好(范围更广)的名称可能不是一个坏主意。

于 2015-12-17T00:28:01.453 回答