工具

Babel 插件(Babel Plugin)

¥Babel Plugin

该插件增加了对服务器端渲染、样式缩小和更好的调试体验的支持。

¥This plugin adds support for server-side rendering, minification of styles, and a nicer debugging experience.

用法(Usage)

¥Usage

首先安装 babel 插件:

¥Install the babel-plugin first:

npm install --save-dev babel-plugin-styled-components

然后将其添加到你的 babel 配置中,如下所示:

¥Then add it to your babel configuration like so:

Note

⚠️ .babelrc 文件中的插件调用顺序很重要。如果你在 babel 配置中使用 env 属性,那么将此插件放入 plugins 数组中是不够的。相反,它需要放入每个环境的插件数组中以保持它首先执行。请参阅 this 了解更多信息。

¥⚠️ The plugin call order in your .babelrc file matters. If you're using the env property in your babel configuration, then putting this plugin into the plugins array won't suffice. Instead it needs to be put into each env's plugins array to maintain it being executed first. See this for more information.

{
  "plugins": ["babel-plugin-styled-components"]
}

服务端渲染(Server-side rendering)

¥Server-side rendering

通过向每个样式组件添加唯一标识符,该插件可以避免由于客户端和服务器上的类生成不同而导致的校验和不匹配。如果你不使用此插件并尝试在服务器端渲染样式组件,React 将在补水期间触发 HTML 属性不匹配警告。

¥By adding a unique identifier to every styled component, this plugin avoids checksum mismatches due to different class generation on the client and on the server. If you do not use this plugin and try to server-side render styled-components React will complain with an HTML attribute mismatch warning during rehydration.

如有必要,你可以使用 ssr 选项禁用它:

¥You can disable it if necessary with the ssr option:

{
  "plugins": [
    [
      "babel-plugin-styled-components",
      {
        "ssr": false
      }
    ]
  ]
}

更好的调试(Better debugging)

¥Better debugging

此选项通过更丰富的输出增强了每个组件上附加的 CSS 类名称,以帮助识别 DOM 中的组件,而无需使用 React DevTools。在你的页面源中你将看到:<button class="Button-asdf123 asdf123" /> 而不仅仅是 <button class="asdf123" />

¥This option enhances the attached CSS class name on each component with richer output to help identify your components in the DOM without React DevTools. In your page source you'll see: <button class="Button-asdf123 asdf123" /> instead of just <button class="asdf123" />.

它还允许你在 React DevTools 中查看组件的 displayName。例如,考虑编写一个渲染 button 元素(称为 MyButton)的样式化组件。它通常会在 DevTools 中显示为 styled.button,但启用 displayName 选项后,它会具有你指定的名称:MyButton

¥It also allows you to see the component's displayName in React DevTools. For example, consider writing a styled component that renders a button element, called MyButton. It will normally show up in DevTools as styled.button, but with the displayName option enabled, it has the name you gave it: MyButton.

这使得你可以更轻松地找到你的组件并找出它们在你的应用中的位置。

¥This makes it easier to find your components and to figure out where they live in your app.

如果你不需要此功能,可以使用 displayName 选项禁用它:

¥If you don't need this feature, you can disable it with the displayName option:

{
  "plugins": [
    [
      "babel-plugin-styled-components",
      {
        "displayName": false
      }
    ]
  ]
}

控制组件 displayName(Control the components displayName)

¥Control the components displayName

默认情况下,组件的 displayName 将以文件名作为前缀,以使组件名称尽可能唯一。

¥By default, the displayName of a component will be prefixed with the filename in order to make the component name as unique as possible.

你可以通过禁用 fileName 选项来强制组件 displayName 仅作为组件名称:

¥You can force the component displayName to be solely the component name by disabling the fileName option:

{
  "plugins": [
    [
      "babel-plugin-styled-components",
      {
        "fileName": false
      }
    ]
  ]
}

你可能想要这样做的一个例子是用 enzyme 测试组件。虽然你始终可以使用 .find(ComponentName),但绝对可以使用 .find("ComponentName") 通过其显示名称来搜索组件。在后一种情况下,你需要禁用 fileName 选项。如果你确实希望仅将其用于测试,请确保仅在你的测试环境下添加它。

¥One example you might want to do this, is testing components with enzyme. While you can always use .find(ComponentName) it's definitely possible to search component by its displayName with .find("ComponentName"). In the latter case you will need to disable the fileName option. If you do want this for testing only, make sure to add this only under your test environment.

控制哪些文件名没有意义(Control which file names are meaningless)

¥Control which file names are meaningless

常见的模式是将组件放入 Button/index.jsx 而不是 Button.jsx。默认情况下,如果 fileName 选项设置为 true,插件将使用目录名 (<button class="Button-asdf123 asdf123" />) 而不是文件名 (<button class="index-asdf123 asdf123" />) 生成显示名称,因为前者提供更多信息。

¥A common pattern is to put components in Button/index.jsx instead of Button.jsx. By default, if the fileName option is set to true, the plugin will generate the display name using the directory name (<button class="Button-asdf123 asdf123" />) instead of the file name (<button class="index-asdf123 asdf123" />), because the former provides more information.

meaninglessFileNames 选项允许自定义与样式组件功能描述无关的文件名列表,因此应使用目录名:

¥The meaninglessFileNames option allows to customize the list of file names that are not relevant to the description of a styled component's functionality, and hence the directory name should be used instead:

{
  "plugins": [
    [
      "babel-plugin-styled-components",
      {
        "meaninglessFileNames": ["index", "styles"]
      }
    ]
  ]
}

例如,将 styles 添加到列表中将使你能够将样式化组件存储在 Button/styles.js 文件中。

¥For example, adding styles to the list would enable you to store your styled components in a Button/styles.js file.

该选项默认为 ["index"]

¥This option defaults to ["index"].

如果 fileNamedisplayName 设置为 false,则此选项无效。

¥If either fileName or displayName are set to false, this option has no effect.

压缩(Minification)

¥Minification

该插件执行两种类型的缩小:一个删除 CSS 中的所有空白和注释,另一个 转译标记模板字面量,将有值的字节保留在包中。

¥Two types of minifications are performed by this plugin: one removes all whitespace & comments from your CSS and the other transpiles tagged template literals, keeping valuable bytes out of your bundles.

如果需要,你可以通过 babel 配置禁用此行为:

¥If desired, you can disable this behavior via babel configuration:

{
  "plugins": [
    ["babel-plugin-styled-components", {
      "minify": false,
      "transpileTemplateLiterals": false
    }]
  ]
}

消除死代码(Dead Code Elimination)

¥Dead Code Elimination

由于样式组件的转译和构造方式,默认情况下缩小器无法正确地对它们执行死代码消除,因为它们被认为具有副作用。但是,可以启用一项名为 "纯注释" 的功能来帮助此过程。

¥Due to how styled components are transpiled and constructed, by default minifiers cannot properly perform dead code elimination on them because they are assumed to have side effects. However, there is a feature that can be enabled to aid this process called "pure annotation".

{
  "plugins": [
    ["babel-plugin-styled-components", {
      "pure": true
    }]
  ]
}

它利用 babel 辅助程序使用 #__PURE__ JS 注释来标记每个样式组件和库辅助程序,一些压缩器使用该注释来克服上述问题。

¥It utilizes a babel helper to tag each styled component and library helper with the #__PURE__ JS comment that some minifiers use to overcome the aforementioned issue.

模板字符串转译(Template String Transpilation)

¥Template String Transpilation

该插件将 styled-components 标记的模板字面量转换为比 Babel 通常创建的更小的表示形式。

¥This plugin transpiles styled-components tagged template literals down to a smaller representation than what Babel normally creates.

等等,转译标记模板字面量?Babel 本身不这样做吗?🤔 使用 Babel,你可能会将 ES2015+ JavaScript 转译为符合 ES5 的代码,以支持旧版浏览器。最流行推荐的基本 Babel 预设 (es2015 / env / latest) 包括 babel-plugin-transform-es2015-template-literals 转换,以使标记模板字面量在旧版浏览器中工作,但有一个警告:该转换的输出非常冗长。这样做是为了满足规范要求。

¥Wait, transpiling tagged template literals? Doesn't Babel do this natively? 🤔 With Babel, you're likely transpiling ES2015+ JavaScript to ES5-compliant code for older browser support. The most popularly recommended base Babel presets (es2015 / env / latest) include the babel-plugin-transform-es2015-template-literals transform to make tagged template literals work in older browsers, but there is a caveat: output of that transform is quite verbose. It's done this way to meet specification requirements.

以下是使用 babel-preset-latest 处理的转译代码示例:

¥Here's an example of the transpiled code processed with babel-preset-latest:

var _templateObject = _taggedTemplateLiteral(['width: 100%;'], ['width: 100%;'])
function _taggedTemplateLiteral(strings, raw) {
  return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } }))
}
var Simple = _styledComponents2.default.div(_templateObject)

styled-components 不需要完整的规范兼容性。我们的 Babel 插件会将附加到样式组件的模板字面量转换为稍微不同的较小形式,该形式仍然可以在旧版浏览器中使用,但占用空间要小得多。

¥styled-components does not require full spec compatibility. Our Babel plugin will transpile template literals attached to styled components to a slightly different, smaller form which still works in older browsers but has a much smaller footprint.

这是前面使用 styled-components babel 插件和 { transpileTemplateLiterals: true } 选项的示例:

¥Here's the previous example with the styled-components babel plugin on and the { transpileTemplateLiterals: true } option:

var Simple = _styledComponents2.default.div(['width: 100%;'])

该插件也足够智能,不会修改属于其他库和用例的标记模板字面量:

¥The plugin is also smart enough to not modify tagged template literals belonging to other libraries and use cases:

// Following will be converted:
styled.div``
keyframe``
css```some text` // But this will not be converted:


// Here the outer template literal will be converted
// because it's attached to the component factory,
// but the inner template literals will not be touched:
styled.div`
  color: ${light ? `white` : `black`};
`

你可以使用 transpileTemplateLiterals 选项禁用此功能:

¥You can disable this feature with the transpileTemplateLiterals option:

{
  "plugins": [
    [
      "babel-plugin-styled-components",
      {
        "transpileTemplateLiterals": false
      }
    ]
  ]
}

请在我们专门的解释部分阅读有关 标记模板字面量 的更多信息。

¥Read more about Tagged Template Literals in our dedicated section explaining them.

命名空间(Namespace)

¥Namespace

命名空间将确保你的类名是唯一的;当你使用可能发生类名冲突的微前端时,此设置非常方便。

¥The namespace will ensure that your class names will be unique; this setting is handy when you are working with micro frontends where class name collision can occur.

如果需要,你可以通过 babel 配置启用此行为:

¥If desired, you can enable this behavior via babel configuration:

{
  "plugins": [
    ["babel-plugin-styled-components", {
      "namespace": "my-app"
    }]
  ]
}

以下是启用 namespace 时处理的转译代码示例:

¥Here's an example of the transpiled code processed with namespace enabled:

_styledComponents2.default.div.withConfig({
  displayName: 'code__before',
  componentId: 'my-app__sc-3rfj0a-1',
})(['color:blue;'])
Note

⚠️ 该功能从 1.11 版本开始提供。

¥⚠️ This feature is available from version 1.11.

SWC 插件(SWC Plugin)

¥SWC Plugin

该插件增加了对服务器端渲染的支持、样式的缩小以及在 SWC 编译器中使用样式组件时更好的调试体验。

¥This plugin adds support for server-side rendering, minification of styles, and better debugging experience when using styled-components with the SWC compiler.

用法(Usage)

¥Usage

首先,安装 @swc/plugin-styled-components@swc/core 软件包:

¥First, install the @swc/plugin-styled-components and @swc/core packages:

npm install --save-dev @swc/plugin-styled-components @swc/core

然后,将该插件添加到你的 .swcrc 配置文件中:

¥Then, add the plugin to your .swcrc configuration file:

{
  "jsc": {
    "experimental": {
      "plugins": [
        [
          "@swc/plugin-styled-components",
          {
            "displayName": true,
            "ssr": true
          }
        ]
      ]
    }
  }
}

选项(Options)

¥Options

  • displayName

    • 描述:通过更丰富的输出增强每个组件上附加的 CSS 类名称,以帮助识别 DOM 中的组件,而无需使用 React DevTools。它还允许你在 React DevTools 中查看组件的 displayName

      ¥Description: Enhances the attached CSS class name on each component with richer output to help identify your components in the DOM without React DevTools. It also allows you to see the component's displayName in React DevTools.

    • 类型:布尔值

      ¥Type: Boolean

    • 默认:true

      ¥Default: true

    • 值:truefalse

      ¥Values: true or false

  • ssr

    • 描述:为每个样式组件添加唯一标识符,以避免由于客户端和服务器上的类生成不同而导致校验和不匹配。有助于服务器端渲染 (SSR)。

      ¥Description: Adds a unique identifier to every styled component to avoid checksum mismatches due to different class generation on the client and on the server. Helps in server-side rendering (SSR).

    • 类型:布尔值

      ¥Type: Boolean

    • 默认:true

      ¥Default: true

    • 值:truefalse

      ¥Values: true or false

  • fileName

    • 描述:控制组件的 displayName 是以文件名为前缀还是仅以组件名称为前缀。

      ¥Description: Controls whether the displayName of a component will be prefixed with the filename or solely the component name.

    • 类型:布尔值

      ¥Type: Boolean

    • 默认:true

      ¥Default: true

    • 值:truefalse

      ¥Values: true or false

  • meaninglessFileNames

    • 描述:允许自定义与样式组件功能描述无关的文件名列表。使用目录名称代替。

      ¥Description: Allows customizing the list of file names that are not relevant to the description of a styled component's functionality. Uses directory names instead.

    • 类型:字符串数组

      ¥Type: Array of strings

    • 默认:["index", "styles"]

      ¥Default: ["index", "styles"]

    • 值:表示无意义文件名的任何字符串数组。

      ¥Values: Any array of strings representing meaningless file names.

  • minify

    • 描述:通过删除所有空格和注释来缩小 CSS。还将标记的模板字面量转换为较小的表示形式。

      ¥Description: Minifies your CSS by removing all whitespace and comments. Also transpiles tagged template literals to a smaller representation.

    • 类型:布尔值

      ¥Type: Boolean

    • 默认:true

      ¥Default: true

    • 值:truefalse

      ¥Values: true or false

  • transpileTemplateLiterals

    • 描述:将 styled-components 标记的模板字面量转换为较小的表示形式。有助于减小打包包的大小。

      ¥Description: Transpiles styled-components tagged template literals to a smaller representation. Helps reduce bundle size.

    • 类型:布尔值

      ¥Type: Boolean

    • 默认:true

      ¥Default: true

    • 值:truefalse

      ¥Values: true or false

  • pure

    • 描述:启用名为 "纯注释" 的功能来帮助样式组件上的死代码消除过程。

      ¥Description: Enables a feature called "pure annotation" to aid dead code elimination process on styled components.

    • 类型:布尔值

      ¥Type: Boolean

    • 默认:false

      ¥Default: false

    • 值:truefalse

      ¥Values: true or false

  • namespace

    • 描述:确保你的类名是唯一的,这在使用可能发生类名冲突的微前端时很有用。

      ¥Description: Ensures that your class names will be unique, useful when working with micro-frontends where class name collisions can occur.

    • 类型:字符串

      ¥Type: String

    • 默认:undefined

      ¥Default: undefined

    • 值:表示所需名称空间的任何字符串。

      ¥Values: Any string representing the desired namespace.

服务端渲染(Server-side rendering)

¥Server-side rendering

通过向每个样式组件添加唯一标识符,该插件可以避免由于客户端和服务器上的类生成不同而导致的校验和不匹配。如果你不使用此插件并尝试在服务器端渲染样式组件,React 将在补水期间触发 HTML 属性不匹配警告。

¥By adding a unique identifier to every styled component, this plugin avoids checksum mismatches due to different class generation on the client and on the server. If you don't use this plugin and try to server-side render styled components, React will complain with an HTML attribute mismatch warning during rehydration.

你可以通过将 ssr 选项设置为 false 来禁用此功能:

¥You can disable this feature by setting the ssr option to false:

{
  "jsc": {
    "experimental": {
      "plugins": [
        [
          "@swc/plugin-styled-components",
          {
            "ssr": false
          }
        ]
      ]
    }
  }
}

更好的调试(Better Debugging)

¥Better Debugging

此选项通过更丰富的输出增强了每个组件上附加的 CSS 类名称,以帮助识别 DOM 中的组件,而无需使用 React DevTools。它还允许你在 React DevTools 中查看组件的 displayName

¥This option enhances the attached CSS class name on each component with richer output to help identify your components in the DOM without React DevTools. It also allows you to see the component's displayName in React DevTools.

如果你不需要此功能,可以通过将 displayName 选项设置为 false 来禁用它:

¥If you don't need this feature, you can disable it by setting the displayName option to false:

{
  "jsc": {
    "experimental": {
      "plugins": [
        [
          "@swc/plugin-styled-components",
          {
            "displayName": false
          }
        ]
      ]
    }
  }
}

控制组件 displayName(Control the components displayName)

¥Control the components displayName

默认情况下,组件的 displayName 将以文件名作为前缀,以使组件名称尽可能唯一。

¥By default, the displayName of a component will be prefixed with the filename in order to make the component name as unique as possible.

你可以通过禁用 fileName 选项来强制组件 displayName 仅作为组件名称:

¥You can force the component displayName to be solely the component name by disabling the fileName option:

{
 "jsc": {
   "experimental": {
     "plugins": [
       [
         "@swc/plugin-styled-components",
         {
           "fileName": false
         }
       ]
     ]
   }
 }
}

控制哪些文件名没有意义(Control which file names are meaningless)

¥Control which file names are meaningless

常见的模式是将组件放入 Button/index.jsx 而不是 Button.jsx。默认情况下,如果 fileName 选项设置为 true,则插件将使用目录名(<button class="Button-asdf123 asdf123" />)而不是文件名(<button class="index-asdf123 asdf123" />)生成 displayName,因为前者提供了更多信息。

¥A common pattern is to put components in Button/index.jsx instead of Button.jsx. By default, if the fileName option is set to true, the plugin will generate the displayName using the directory name (<button class="Button-asdf123 asdf123" />) instead of the file name (<button class="index-asdf123 asdf123" />), because the former provides more information.

meaninglessFileNames 选项允许你自定义与样式组件功能描述无关的文件名列表,因此应使用目录名:

¥The meaninglessFileNames option allows you to customize the list of file names that are not relevant to the description of a styled component's functionality, and hence the directory name should be used instead:

{
 "jsc": {
   "experimental": {
     "plugins": [
       [
         "@swc/plugin-styled-components",
         {
           "meaninglessFileNames": ["index", "styles"]
         }
       ]
     ]
   }
 }
}

压缩(Minification)

¥Minification

该插件通过删除所有空格和注释来缩小你的 CSS。它还将标记的模板字面量转换为更小的表示形式,从而将有价值的字节保留在包之外。

¥This plugin minifies your CSS by removing all whitespace and comments. It also transpiles tagged template literals to a smaller representation, keeping valuable bytes out of your bundles.

如果需要,你可以通过将 minify 选项设置为 false 来禁用此行为:

¥If desired, you can disable this behavior by setting the minify option to false:

{
 "jsc": {
   "experimental": {
     "plugins": [
       [
         "@swc/plugin-styled-components",
         {
           "minify": false,
           "transpileTemplateLiterals": false
         }
       ]
     ]
   }
 }
}

消除死代码(Dead Code Elimination)

¥Dead Code Elimination

由于样式组件的转译和构造方式,默认情况下,压缩器无法正确地对它们执行死代码消除,因为它们被认为具有副作用。但是,可以启用一项名为 "纯注释" 的功能来帮助此过程。

¥Due to how styled components are transpiled and constructed, by default, minifiers cannot properly perform dead code elimination on them because they are assumed to have side effects. However, there is a feature that can be enabled to aid this process called "pure annotation".

{
 "jsc": {
   "experimental": {
     "plugins": [
       [
         "@swc/plugin-styled-components",
         {
           "pure": true
         }
       ]
     ]
   }
 }
}

模板字符串转译(Template String Transpilation)

¥Template String Transpilation

与 Babel 插件类似,该插件将 styled-components 标记的模板字面量转换为比 SWC 通常创建的更小的表示形式。这有助于减小打包包的大小。

¥Similar to the Babel plugin, this plugin transpiles styled-components tagged template literals to a smaller representation than what SWC normally creates. This helps reduce the bundle size.

你可以通过将 transpileTemplateLiterals 选项设置为 false 来禁用此功能:

¥You can disable this feature by setting the transpileTemplateLiterals option to false:

{
 "jsc": {
   "experimental": {
     "plugins": [
       [
         "@swc/plugin-styled-components",
         {
           "transpileTemplateLiterals": false
         }
       ]
     ]
   }
 }
}

命名空间(Namespace)

¥Namespace

namespace 选项确保你的类名是唯一的,这在使用可能发生类名冲突的微前端时非常方便。

¥The namespace option ensures that your class names will be unique, which is handy when working with micro-frontends where class name collisions can occur.

要启用此行为,请在配置中设置 namespace 选项:

¥To enable this behavior, set the namespace option in your configuration:

{
 "jsc": {
   "experimental": {
     "plugins": [
       [
         "@swc/plugin-styled-components",
         {
           "namespace": "my-app"
         }
       ]
     ]
   }
 }
}

Babel 宏(Babel Macro)

¥Babel Macro

| v4 | v5

Note

由于缺乏使用和其他消费者不必要的膨胀,此功能在 v6.1 中被删除。更多信息

¥This functionality was removed in v6.1 due to lack of usage and unnecessary bloat for other consumers. More info

Babel 宏 作为一个功能齐全的选项正在迅速获得发展,它允许像 create-react-app 这样的零配置项目进行高级代码转译。

¥Babel macros are quickly gaining steam as a full-featured option to allow advanced code transpilation for zero-config projects like create-react-app.

如果你的脚手架设置为 babel-plugin-macros,则只需使用新的 styled-components/macro 导入而不是 styled-components

¥If your scaffold is set up with babel-plugin-macros, then simply use the new styled-components/macro import instead of styled-components:

import styled, { createGlobalStyle } from 'styled-components/macro'


const Thing = styled.div`
  color: red;
`


const GlobalStyle = createGlobalStyle`
  body {
    color: 'white';
  }
`

该宏合并了 我们的 babel 插件 的所有功能,同时允许未弹出的工具处理构建过程的 Babel 部分。特别感谢 Luc Leray (@lucleray) 让这一切发生!

¥The macro incorporates all the functionality of our babel plugin while allowing the unejected tooling to handle the Babel part of the build process. Special thanks to Luc Leray (@lucleray) for making this happen!

实验配置(EXPERIMENTAL Config)

¥EXPERIMENTAL Config

babel-plugin-macros 使用 cosmiconfig 读取 babel-plugin-macros 配置,该配置可以位于导入文件目录中的以下任意文件中:

¥babel-plugin-macros uses cosmiconfig to read a babel-plugin-macros configuration which can be located in any of the following files up the directories from the importing file:

  • .babel-plugin-macrosrc

  • .babel-plugin-macrosrc.json

  • .babel-plugin-macrosrc.yaml

  • .babel-plugin-macrosrc.yml

  • .babel-plugin-macrosrc.js

  • babel-plugin-macros.config.js

  • babelMacrospackage.json

    ¥babelMacros in package.json

然后,你可以在 styledComponents 条目中指定与 我们的 babel 插件 相同的选项:

¥You can then specify the same options as our babel plugin in styledComponents entry:

// babel-plugin-macros.config.js
module.exports = {
  // ...
  // Other macros config
  styledComponents: {
    pure: true,
  },
}

欲了解更多信息,请参阅 babel-plugin-macros 的实验配置

¥For more information, see EXPERIMENTAL config for babel-plugin-macros .

强制执行宏导入(Enforce macro imports)

¥Enforce macro imports

你可能希望确保在整个项目中一致地从宏导入对象。这可以通过使用 ESLint 中的 no-restricted-imports 规则来实现:

¥You may want to ensure that objects are consistently imported from the macro across your project. This can be achieved by using a no-restricted-imports rule from ESLint:

"no-restricted-imports": [
  "error",
  {
    "paths": [{
      "name": "styled-components",
      "message": "Please import from styled-components/macro."
    }],
    "patterns": [
      "!styled-components/macro"
    ]
  }
]

TypeScript 插件(TypeScript Plugin)

¥TypeScript Plugin

typescript-plugin-styled-components 是 TypeScript 的插件,可为你提供更好的调试体验。

¥typescript-plugin-styled-components is a plugin for TypeScript that gives you a nicer debugging experience.

Note

⚠️ TypeScript 不允许直接从命令行编译器 tsc 使用任何插件或转换器。因此,该插件仅适用于构建工具链,例如带有 TypeScript 加载器之一的 webpack。如果你想投票的话,有 一个悬而未决的问题 可以给 tsc 带来插件!

¥⚠️ TypeScript does not allow to use any plugin or transformer directly from the command line compiler tsc. So the plugin only works with build toolchains such as webpack with one of TypeScript loaders. There's an open issue to bring plugins to tsc though if you want to upvote it!

请参阅 该项目的 GitHub 存储库 了解文档。

¥Please refer to the project's GitHub repo for documentation.

Jest 集成(Jest Integration)

¥Jest Integration

Jest 风格的组件 是一组用于使用 Jest 测试样式组件的实用程序。该包改善了快照测试体验,并提供了一个全新的匹配器来对样式规则进行期望。

¥Jest Styled Components is a set of utilities for testing Styled Components with Jest. This package improves the snapshot testing experience and provides a brand new matcher to make expectations on the style rules.

安装(Installation)

¥Installation

npm install --save-dev jest-styled-components

快照测试(Snapshot Testing)

¥Snapshot Testing

当我们使用样式化组件构建 UI 时,我们希望确保输出不会意外更改。快照测试是测试 React 组件的绝佳方法,该包通过向快照添加样式使体验变得更加愉快。

¥When we are building a UI with Styled Components, we want to make sure the output doesn't change unexpectedly. Snapshot testing is an excellent way to test React components, and this package makes the experience even more delightful by adding the style to the snapshots.

这是一个测试示例:

¥Here's an example of a test:

import React from 'react'
import styled from 'styled-components'
import renderer from 'react-test-renderer'
import 'jest-styled-components'


const Button = styled.button`
  color: red;
`


test('it works', () => {
  const tree = renderer.create(<Button />).toJSON()
  expect(tree).toMatchSnapshot()
})

这是生成的快照的示例:

¥And here's an example of the resulting snapshot:

exports[`it works 1`] = `
.c0 {
  color: red;
}


<button
  className="c0"
/>
`

如需真实世界的演示,请查看 该网站的存储库

¥For a real world demo, check out this website's repository.

toHaveStyleRule(toHaveStyleRule)

如果我们只想检查某个元素是否应用了特定样式,则可以使用 toHaveStyleRule 匹配器。此函数采用两个必需参数,一个属性(字符串)和一个值(字符串或 RegExp),以及一个可选对象,用于搜索嵌套在 at 规则中的规则或向类选择器添加修饰符。

¥If we only want to check whether a particular style has been applied to an element, we can use the toHaveStyleRule matcher. This function takes two required parameters, a property (string) and a value (string or RegExp), and an optional object to search for rules nested within an at-rule or to add modifiers to the class selector.

import React from 'react'
import styled from 'styled-components'
import renderer from 'react-test-renderer'
import 'jest-styled-components'


const Button = styled.button`
  color: red;
  @media (max-width: 640px) {
    &:hover {
      color: green;
    }
  }
`


test('it works', () => {
  const tree = renderer.create(<Button />).toJSON()
  expect(tree).toHaveStyleRule('color', 'red')
  expect(tree).toHaveStyleRule('color', 'green', {
    media: '(max-width: 640px)',
    modifier: ':hover',
  })
})

Stylelint(Stylelint)

stylelint 检查你的 样式组件

¥Lint your styled components with stylelint!

安装(Installation)

¥Installation

对于 stylelint v15+(推荐)(For stylelint v15+ (recommended))

¥For stylelint v15+ (recommended)

第一次配置 stylelint (v15+)?按着这些次序:

¥Configuring stylelint (v15+) for the first time? Follow these steps:

你需要:

¥You need:

npm install --save-dev \
  stylelint \
  stylelint-config-standard \
  postcss-styled-syntax

.stylelintrc 文件添加到项目的根目录:

¥Add a .stylelintrc file to the root of your project:

{
  "extends": [
    "stylelint-config-standard"
  ],
  "customSyntax": "postcss-styled-syntax"
}

对于 stylelint v14 及更低版本(For stylelint v14 and below)

¥For stylelint v14 and below

你需要:

¥You need:

Note

我们建议使用 Stylelint v9+,因为它添加了一些功能,使我们能够报告 CSS 语法错误的正确行号

¥We recommend using Stylelint v9+ as this has added features that allow us to report correct line numbers on CSS syntax errors

npm install --save-dev \
  stylelint \
  stylelint-processor-styled-components \
  stylelint-config-styled-components \
  stylelint-config-recommended

.stylelintrc 文件添加到项目的根目录:

¥Add a .stylelintrc file to the root of your project:

{
  "processors": [
    "stylelint-processor-styled-components"
  ],
  "extends": [
    "stylelint-config-recommended",
    "stylelint-config-styled-components"
  ]
}

设置(Setup)

¥Setup

你需要运行 stylelint。将 lint:css 脚本添加到 package.json 中,该脚本运行 stylelint,并为所有样式组件添加一个 glob:

¥You need to run stylelint. Add a lint:css script to your package.json which runs stylelint with a glob to all of your styled components:

{
  "scripts": {
    "lint:css":"stylelint './src/**/*.js'"
  }
}
Note

处理器会忽略不包含任何 styled-components 的 javascript 文件,因此只要将其限制为 javascript(或 TypeScript),就不必担心太宽泛。

¥The processor ignores javascript files that don't contain any styled-components, so don't worry about being too broad as long as you restrict it to javascript (or TypeScript).

现在你可以通过运行脚本来检查 CSS 了!🎉

¥Now you can lint your CSS by running the script! 🎉

npm run lint:css
Note

Stylelint --fix 选项在版本 15+ 上具有相同的规则。

¥Stylelint --fix option works with same rules on version 15+.

Webpack(Webpack)

如果你想在构建时进行 lint,而不是作为单独的命令,则可以使用 stylelint-custom-processor-loader for webpack。

¥If you want to lint on build, rather than as a separate command, you can use the stylelint-custom-processor-loader for webpack.

stylelint-config-styled-components(stylelint-config-styled-components)

使用此处理器时,一些 stylelint 规则会抛出无法阻止的错误,例如 no-empty-sourceno-missing-end-of-source-newline。我们还需要执行一些规则,例如 no-vendor-prefix 规则。(styled-components 浏览器会自动为你的代码添加前缀,因此你无需手动执行此操作)

¥When using this processor a couple of stylelint rules throw errors that cannot be prevented, like no-empty-source or no-missing-end-of-source-newline. There's also a couple rules which we need to enforce, like no-vendor-prefix rules. (styled-components automatically vendor prefixes your code, so you don't need to do it manually)

stylelint-config-styled-components 将自动禁用导致冲突的规则。

¥The stylelint-config-styled-components will automatically disable rules that cause conflicts.

Note

你可以覆盖自定义 .stylelintrc 中共享配置中定义的规则。

¥You can override rules defined in shared configs in your custom .stylelintrc.

与其他库一起使用(Usage with other libraries)

¥Usage with other libraries

其他一些库也使用标记模板字面量实现 styled.x 模式。只要它们使用 styled 关键字,该处理器也会对那些标记的模板字面量中的 CSS 进行 lint 处理。

¥Some other libraries also implement the styled.x pattern with tagged template literals. This processor will lint the CSS in those tagged template literals too, as long as they use the styled keyword.

如果你想将处理器与另一个库一起使用,但你还想更改关键字(例如写 cool.div 而不是 styled.div),请使用 moduleName 选项:

¥If you want to use the processor with another library but you also want to change the keyword (e.g. to write cool.div instead of styled.div) use the moduleName option:

import cool from 'other-library';


const Button = cool.button`
  color: blue;
`;
{
  "processors": [
    [
      "stylelint-processor-styled-components",
      {
        "moduleName": "other-library"
      }
    ]
  ]
}
Note

该双数组是故意的,但仅在设置选项时才需要,请参阅 处理器配置文档

¥That double array is on purpose but only necessary if you set options, see the processors configuration docs.

Note

我们只正式支持 styled-components,但希望其他库也能从该处理器中受益。

¥We only officially support styled-components, but the hope is that other libraries can also benefit from the processor.

插值标记(使用 stylelint-processor-styled-components)(Interpolation tagging (with stylelint-processor-styled-components))

¥Interpolation tagging (with stylelint-processor-styled-components)

有时 stylelint 可能会抛出错误(例如 CssSyntaxError),即使你的 CSS 没有任何问题。这通常是由于插值造成的,更具体地说,是处理器不知道你正在插值的内容。

¥Sometimes stylelint can throw an error (e.g. CssSyntaxError) even though nothing is wrong with your CSS. This is often due to an interpolation, more specifically the fact that the processor doesn't know what you're interpolating.

一个简化的例子:

¥A simplified example:

const something = 'background';


const Button = styled.div`
  ${something}: papayawhip;
`;

当你的样式中有插值时,处理器无法知道它们是什么,因此它会做出很好的猜测,并将它们替换为语法上等效的占位符值。由于 stylelint 不是代码流分析工具,因此它无法涵盖所有边缘情况,并且处理器会时不时地出错。

¥When you have interpolations in your styles the processor can't know what they are, so it makes a good guess and replaces them with a syntactically equivalent placeholder value. Since stylelint is not a code flow analysis tool this doesn't cover all edge cases and the processor will get it wrong every now and then.

插值标记允许你告诉处理器插值是什么,以防它猜测错误;然后它可以根据你的标签将插值替换为语法正确的值。

¥Interpolation tagging allows you to tell the processor what an interpolation is in case it guesses wrong; it can then replace the interpolation with a syntactically correct value based on your tag.

例如:

¥For example:

const something = 'background';


const Button = styled.div`
  // Tell the processor that "something" is a property
  ${/* sc-prop */ something}: papayawhip;
`;

现在处理器知道 something 插值是一个属性,并且它可以用 linting 属性替换插值。

¥Now the processor knows that the something interpolation is a property, and it can replace the interpolation with a property for linting.

要标记插值,请在插值的开头或结尾添加注释。(${/* sc-tag */ foo}${bar /* sc-tag */})标签以 sc- 开头,如果指定,标签将覆盖处理器对插值的猜测。

¥To tag an interpolation add a comment at either the start or the end of the interpolation. (${/* sc-tag */ foo} or ${bar /* sc-tag */}) Tags start with sc- and, if specified, a tag overrides the processors guess about what the interpolation is.

标签(Tags)

¥Tags

支持的标签的完整列表:

¥The full list of supported tags:

  • sc-block

  • sc-selector

  • sc-declaration

  • sc-property

  • sc-value

Note

如果你对词汇有疑问,可以参考 这个 CSS 词汇表 的例子。

¥If you are in doubt of the vocabulary you can refer to this CSS vocabulary list with examples.

例如,当你插入另一个样式组件时,你真正插入的是其唯一的选择器。由于处理器不知道这一点,因此你可以告诉它在 linting 时将其替换为选择器:

¥For example, when you interpolate another styled component, what you really interpolate is its unique selector. Since the processor doesn't know that, you can tell it to replace it with a selector when linting:

const Wrapper = styled.div`
  ${/* sc-selector */ Button} {
    color: red;
  }
`;

你还可以使用速记标签来避免代码混乱。例如:

¥You can also use shorthand tags to avoid cluttering the code. For example:

const Wrapper = styled.div`
  ${/* sc-sel */ Button} {
    color: red;
  }
`;

sc-custom(sc-custom)

sc-custom 旨在用作最后的应急方案。如果可能的话,最好使用标准标签!

¥**sc-custom is meant to be used as a last resort escape hatch. Prefer to use the standard tags if possible!**

除了上述标准标签之外,处理器还具有 sc-custom 标签,可让你涵盖更独特和不常见的边缘情况。使用 sc-custom 标签,你可以自己决定占位符值。

¥On top of the above standard tags the processor also has the sc-custom tag to allow you to cover more unique and uncommon edge cases. With the sc-custom tag you can decide yourself what the placeholder value will be.

例如:

¥For example:

// Switch between left and right based on language settings passed through via the theme
const rtlSwitch = (props) => (props.theme.dir === 'rtl' ? 'left' : 'right');


const Button = styled.button`
  background: green;
  // Tell the processor to replace the interpolation with "left"
  // when linting
  margin-${/* sc-custom "left" */ rtlSwitch}: 12.5px;
`;

语法注释(Syntax notes)

¥Syntax notes

从 JS/CSS 中关闭规则(Turning rules off from within your JS/CSS)

¥Turning rules off from within your JS/CSS

在标记模板字面量的内部和外部使用 stylelint-disable 注释(请参阅 stylelint 文档 了解所有允许的语法)关闭规则。

¥Turn off rules with stylelint-disable comments (see the stylelint documentation for all allowed syntax) both inside and outside of the tagged template literals.

import React from 'react';
import styled from 'styled-components';


// Disable stylelint from within the tagged template literal
const Wrapper = styled.div`
  /* stylelint-disable */
  background-color: 123;
`;


// Or from the JavaScript around the tagged template literal
/* stylelint-disable */
const Wrapper = styled.div`
  background-color: 123;
`;

模板字面样式和缩进(Template literal style and indentation)

¥Template literal style and indentation

为了让 stylelint 正确应用缩进规则,处理器需要对样式进行一些有态度的预处理,这导致我们只正式支持一种缩进样式。(支持的样式是所有文档中显示的 "default" 样式)

¥In order to have stylelint correctly apply indentation rules the processor needs to do a bit of opinionated preprocessing on the styles, which results in us only officially supporting one indentation style. (the supported style is the "default" one as shown in all the documentation)

重要的是,将结束反引号放在缩进的基本级别上,如下所示:

¥The important thing is that you put the closing backtick on the base level of indentation as follows:

正确的

¥Right

if (condition) {
  const Button = styled.button`
    color: red;
  `;
}

错误的

¥Wrong

if (condition) {
  const Button = styled.button`
    color: red;
`
}
if (condition) {
  const Button = styled.button`
    color: red;`
}

可能同时支持其他标记模板字面量样式,但除非使用上述样式,否则不会处理有关缩进的问题。

¥It may be that other tagged template literal styles are coincidentally supported, but no issues will be handled regarding indentation unless the above style was used.

风格主题(Styled Theming)

¥Styled Theming

使用 styled-theming 为你的样式组件创建主题

¥Create themes for your styled components using styled-theming

阅读 介绍性博客文章

¥Read the introductory blog post

安装(Install)

¥Install

首先安装 babel 插件:

¥Install the babel-plugin first:

npm install --save styled-theming

示例(Example)

¥Example

import React from 'react'
import styled, { ThemeProvider } from 'styled-components'
import theme from 'styled-theming'


const boxBackgroundColor = theme('mode', {
  light: '#fff',
  dark: '#000',
})


const Box = styled.div`
  background-color: ${boxBackgroundColor};
`


export default function App() {
  return (
    <ThemeProvider theme={{ mode: 'light' }}>
      <Box>Hello World</Box>
    </ThemeProvider>
  )
}

API(API)

<ThemeProvider>(<ThemeProvider>)

styled-components 文档

¥See styled-components docs

<ThemeProvider> 是样式组件的一部分,但对于样式主题是必需的。

¥<ThemeProvider> is part of styled-components, but is required for styled-theming.

import { ThemeProvider } from 'styled-components'

<ThemeProvider> 接受单个 prop theme,你应该通过字符串或 getter 函数传递一个对象。例如:

¥<ThemeProvider> accepts a single prop theme which you should pass an object with either strings or getter functions. For example:

<ThemeProvider theme={{ mode: "dark", size: "large" }}>
<ThemeProvider theme={{ mode: modes => modes.dark, size: sizes => sizes.large }}>

你通常应该在应用的根目录中设置 <ThemeProvider>

¥You should generally set up a <ThemeProvider> at the root of your app:

function App() {
  return (
    <ThemeProvider theme={...}>
      {/* rest of your app */}
    </ThemeProvider>
  );
}

theme(name, values)(theme(name, values))

你的大部分主题将通过此功能完成。

¥Most of your theming will be done with this function.

name 应与 <ThemeProvider> 主题中的键之一匹配。

¥name should match one of the keys in your <ThemeProvider> theme.

;<ThemeProvider theme={{ whatever: '...' }} />
theme("whatever", {...});

values 应该是一个对象,其中的键之一将由提供给 <ThemeProvider> 主题的值选择。

¥values should be an object where one of the keys will be selected by the value provided to <ThemeProvider> theme.

<ThemeProvider theme={{ mode: "light" }} />
<ThemeProvider theme={{ mode: "dark" }} />


theme("mode", {
  light: "...",
  dark: "...",
});

该对象的值可以是任何 CSS 值。

¥The values of this object can be any CSS value.

theme("mode", {
  light: "#fff",
  dark: "#000",
});


theme("font", {
  sansSerif: '"Helvetica Neue", Helvetica, Arial, sans-serif',
  serif: 'Georgia, Times, "Times New Roman", serif',
  monoSpaced: "Consolas, monaco, monospace",
});

这些值也可以是返回 CSS 值的函数。

¥These values can also be functions that return CSS values.

theme('mode', {
  light: props => props.theme.userProfileAccentColor.light,
  dark: props => props.theme.userProfileAccentColor.dark,
})

theme 将创建一个函数,你可以将其用作样式组件的 styled 函数中的值。

¥theme will create a function that you can use as a value in styled-component's styled function.

import styled from 'styled-components'
import theme from 'styled-theming'


const backgroundColor = theme('mode', {
  light: '#fff',
  dark: '#000',
})


const Box = styled.div`
  background-color: ${backgroundColor};
`

theme.variants(name, prop, themes)(theme.variants(name, prop, themes))

创建通过附加属性选择的同一组件的变体通常很有用。

¥It's often useful to create variants of the same component that are selected via an additional prop.

为了使主题更容易实现,styled-theming 提供了 theme.variants 函数。

¥To make this easier with theming, styled-theming provides a theme.variants function.

import styled from "styled-components";
import theme from "styled-theming";


const backgroundColor = theme.variants("mode", "variant", {
  default: { light: "gray", dark: "darkgray" },
  primary: { light: "blue", dark: "darkblue" },
  success: { light: "green", dark: "darkgreen" },
  warning: { light: "orange", dark: "darkorange" },
});


const Button = styled.button`
  background-color: ${backgroundColor};
`;


Button.propTypes = {
  variant: PropTypes.oneOf(["default", "primary", "success", "warning"])
};


Button.defaultProps = {
  variant: "default",
};


<Button />
<Button variant="primary" />
<Button variant="success" />
<Button variant="warning" />

语法高亮(Syntax Highlighting)

¥Syntax Highlighting

在模板字面量中编写 CSS 时,你曾经丢失的一件事是语法高亮。我们正在努力在所有编辑器中实现正确的语法高亮。我们目前支持 Atom、Visual Studio Code、WebStorm 以及即将推出的 Sublime Text。

¥The one thing you used to lose when writing CSS in template literals is syntax highlighting. We're working hard on making proper syntax highlighting happening in all editors. We currently have support for Atom, Visual Studio Code, WebStorm, and soon Sublime Text.

这是正确高亮时的样子:

¥This is what it looks like when properly highlighted:

Syntax highlighted styled component

Atom(Atom)

language-babel 的创建者 @gandm 在 Atom 中添加了对 styled-components 的支持!

¥@gandm, the creator of language-babel, has added support for styled-components in Atom!

要获得正确的语法高亮,你所要做的就是为你的 JavaScript 文件安装并使用 language-babel 包!

¥To get proper syntax highlighting, all you have to do is install and use the language-babel package for your JavaScript files!

Sublime Text(Sublime Text)

@garetmckinleyPR 已合并到 babel-sublime 中,但尚未发布到 Package Control。但是,可以直接从 GitHub 安装,如 这个问题 中所述。

¥A PR by @garetmckinley has been merged into babel-sublime but has not been released to Package Control. It is, however, available to install directly from GitHub as described in this issue.

另一个选项是 Naomi by Alexandre Borela,这是 Sublime Text 3 语法高亮定义的集合,它支持开箱即用的 styled-components

¥Another option is Naomi by Alexandre Borela, a collection of syntax highlighting definitions for Sublime Text 3 which supports styled-components out-of-the-box.

Visual Studio Code(Visual Studio Code)

@gandm 的 language-babel 已由 Michael McDermottBabel JavaScript 的名称移植到 VSCode。它为 Babel 语法高亮提供了相同的一体化解决方案,其中包含样式组件。

¥@gandm's language-babel has been ported to VSCode under the name Babel JavaScript by Michael McDermott. It provides the same all-in-one solution for Babel syntax highlighting with styled-components included.

如果你想保持当前的 JavaScript 语法高亮,你可以使用 vscode-styled-components 扩展在 Javascript 文件内提供样式组件语法高亮。你可以像往常一样从 市场 安装它。

¥If you would like to keep your current JavaScript syntax highlighting, you can use the vscode-styled-components extension to provide styled-components syntax highlighting inside your Javascript files. You can install it as usual from the Marketplace.

VIM/NeoVim(VIM / NeoVim)

vim-styled-components 插件为你提供 Javascript 文件内的语法高亮显示。使用常用的插件管理器(如 插件VundlePathogen 等)安装它。

¥The vim-styled-components plugin gives you syntax highlighting inside your Javascript files. Install it with your usual plugin manager like Plug, Vundle, Pathogen, etc.

另外,如果你正在寻找一个很棒的 javascript 语法包,那么 YAJS.vim 绝对不会出错。

¥Also if you're looking for an awesome javascript syntax package you can never go wrong with YAJS.vim.

WebStorm、IntelliJ IDEA、PhpStorm、PyCharm 和 RubyMine(WebStorm, IntelliJ IDEA, PhpStorm, PyCharm, and RubyMine)

¥WebStorm, IntelliJ IDEA, PhpStorm, PyCharm, and RubyMine

webstorm-styled-components 插件为模板字符串中的 CSS 属性和值添加了代码完成和高亮。它还为插值中的 JavaScript 符号提供代码补全和导航。你可以从 IDE 安装它:转到 Preferences | Plugins 并搜索 Styled Components

¥The webstorm-styled-components plugin adds code completion and highlighting for CSS properties and values in the template strings. And it also provides code completion and navigation for JavaScript symbols in the interpolations. You can install it from the IDE: go to Preferences | Plugins and search for Styled Components.

其他编辑(Other Editors)

¥Other Editors

我们可以利用你的帮助来获得对其他编辑器的语法高亮支持!所有这些语法高亮都是由 Styled Components 社区构建的,因此如果你想开始为你的编辑器进行语法高亮,我们很乐意看到它。

¥We could use your help to get syntax highlighting support to other editors! All these syntax highlighting were built by the Styled Components community so if you want to start working on syntax highlighting for your editor, we would love to see it.

继续下一页

常见问题