使用 Pug 模板编写 React 组件。 babel plugin transform react pug

使用 Pug 模板编写 React 组件。

babel-plugin-transform-react-pug 是 babel 的一个插件,它将模板文字中的 pug 语法转换为 jsx。

以这种方式编写您的组件:

jsx
export function ReactComponent(props) {
  return pug`
  .wrapper
    if props.shouldShowGreeting
      p.greeting Hello World!

    button(onClick=props.notify) Click Me
`
}

它将被转换为:

jsx
export function ReactComponent(props) {
  return (
    <div className="wrapper">
      {props.shouldShowGreeting
        ? (
          <p className="greeting">Hello World!</p>
          )
        : null}
      <button onClick={props.notify}>Click Me</button>
    </div>
  )
}

Usage

Syntax

您可以在官方文档中找到语法的完整信息:pugjs.org

Basic example

jsx
function Component(props) {
  return pug`          //- const Component = props => (
  div                                    //-   <div>
    if props.amount > MAX_AMOUNT         //-     {props.amount > MAX_AMOUNT ? (
      OtherComponent(fluid crucial)      //-       <OtherComponent fluid={true} crucial={true} />
    else                                 //-     ) : (
      p You can set bigger amount ;)     //-       <p>You can set bigger amount ;)</p>
                                         //-     )}
    each item, index in props.items      //-     {props.items.map((item, index) => (
      div(key=item.id)                   //-       <div key={item.id}>
        h3 Header #{index + 1}           //-         <h3>Header {index + 1}</h3>
        = item.body                      //-         {item.body}
                                         //-       </div>
                                         //-     )}
                                         //-   </div>
                                         //- )
`
}

如何传递函数和其他原语

jsx
function Component(props) {
  return pug`          //- const Component = props => (
  div                                    //-   <div>
    button(                              //-     <button
      type="button"                      //-       type="button"
      onClick=props.onClick              //-       onClick={props.onClick}
    ) Click Me                           //-     >Click Me</button>
                                         //-
    OtherComponent(                      //-     <OtherComponent
      ...props.objectWithPropsForChild   //-       {...props.objectWithPropsForChild}
      fluid                              //-       fluid={true}
      data-array=[1, 2, 3]               //-       data-array={[1, 2, 3]}
    )                                    //-     />
                                         //-   </div>
                                         //- )
`
}

定义局部变量并在属性中使用javascript

jsx
function Component(props) {
  return pug`          //- const Component = props => (
  Fragment                               //-   <Fragment>
    button(                              //-     <button
      ...one                             //-       {...one}
      ...two                             //-       {...two}
      onClick=() => alert('Hello')       //-       onClick={() => alert('Hello')}
      text='number ' + 10                //-       text={'number ' + 10}
      condition=foo === bar ? foo : bar  //-       condition={foo === bar ? foo : bar}
    )                                    //-     ></button>
                                         //-
    - const variable = format(props.no)  //-
    p Variable is #{variable}            //-     <p>Variable is {format(props.no)}</p>
                                         //-   </Fragment>
                                         //- )
`
}

插值

如果你更喜欢使用插值,你可以。 这可以通过在模板中使用 ${} 来实现。

jsx
function Component(props) {
  return pug`
  ul(className=${props.modifier})
    ${props.items.map((item, index) => pug`li(key=${index}) ${item}`)}
`
}

Eslint integration

安装 eslint-plugin-react-pug 如果你使用 [eslint-plugin-react](https://github.com/yannickcr/ eslint 插件反应)。

CSS 模块

您是否使用 babel 插件专门为 JSX 打开 CSS 模块(例如 babel-plugin-react-css-modules)或使用 用于将样式转换为键值对象的 webpack 加载器,可以将其与哈巴狗一起使用。

  • 使用 babel-plugin-react-css-modules 你需要设置 classAttribute 选项为 styleName 值,仅此而已。
    json
    {
      "plugins": [
        ["transform-react-pug", {
          "classAttribute": "styleName"
        }]
      ]
    }
    
    jsx
    import './styles.css' // .hello{color:red}
    
    const withCorrectStyles = pug`
      div.hello I am a red text
    `
    
  • 使用 webpack 加载器或其他将样式转换为对象的方法
    jsx
    import classes from './styles.css' // .hello{color:green}
    
    const withCorrectStyles = pug`
      div(className=classes.hello) I am a green text
    `
    

    通过将 classAttribute 选项设置为 styleName 值并添加 babel-plugin-transform-jsx-css-modules
    json
    {
      "plugins": [
        ["transform-react-pug", {
          "classAttribute": "styleName"
        }],
        "transform-jsx-css-modules"
      ]
    }
    
    jsx
    import './styles.css' // .hello{color:green}
    
    const withCorrectStyles = pug`
      div.hello I am a green text
    `
    

Install

  1. Install via yarn or npm
    yarn add --dev babel-plugin-transform-react-pug
    
    npm install --save-dev babel-plugin-transform-react-pug
    
  2. Add to babel configuration before transpiling jsx (usually in .babelrc)
    {
      "plugins": [
        "transform-react-pug",
        "transform-react-jsx"
      ]
    }
    
  3. 现在你所有用 pug 编写的模板都可以被 react 和浏览器理解。

Configuration

NameTypeDefaultDescription
classAttributeStringclassName被 PUG 视为“类”的属性名称

classAttribute

Default:

pug`p.one`

=>
<p className="one" />

With "styleName" as value:

pug`p.one`

=>
<p styleName="one" />

create-react-app

create-react-app 集成很棘手,因为它不允许您修改 babel 配置。 有两种记录的可能性:

这很简单,您将在根目录中获得 .babelrc 文件,只需在 transform-react-jsx 之前添加 transform-react-pug 即可。

  • [react-app-rewired]链接到 rewired cra
    按照官方说明重新连接您的应用程序。 然后修改你的config-overrides.js
    diff
    + const {injectBabelPlugin} = require('react-app-rewired');
      module.exports = function override(config, env) {
    -   //do stuff with the webpack config...
    +   config = injectBabelPlugin('transform-react-pug', config);
        return config;
      }
    

React Native

只需将此插件添加到 .babelrc 文件的列表中即可。

diff
  {
-   "presets": ["react-native"]
+   "presets": ["react-native"],
+   "plugins": ["transform-react-pug"]
  }

We don't need transform-react-jsx here because it's coming with react-native preset.

How it works

Coming soon...

Limitations

  • 我们不能在组件名称中使用点,因为 pugjs 将点之后的所有内容都视为类名。 例如,React.Fragment 变成了<React className="Fragment" />,而不是<React.Fragment />
    babel-plugin-transform-jsx-classname-components 提出了一个很好的解决方法。 只需将它添加到 .babelrc 中:
    json
    {
      "plugins": [
        ["transform-jsx-classname-components", {
          "objects": ["React"]
        }]
      ]
    }
    
  • 我们不支持 pug 模板中的 html 语言。 这与 Pug 的承诺 不同。
    但是,您仍然可以使用 标签插值
    pug
    p Good #[strong Morning]
    

FAQ

我可以从其他文件导入模板吗?

简短的回答是否定的,我们不会在不久的将来实施。 看一下 带有小解释的初始请求 (#15)

如何在 IDE(或文本编辑器)中获得语法高亮?

网络风暴

  1. 打开设置
  2. “编辑器” -> “语言注入”
  3. 点击**添加新的“Generic Js”**注入
    [查看如何找到此部分 (youtrack.jetbrains.com/issue/WEB-22106#focus=streamItem-27-2451611-0-0)](https://youtrack.jetbrains.com/issue/WEB-22106 #focus=streamItem-27-2451611-0-0)
    • 名称:Pug In Template Literals (JavaScript)
    • ID:Vue(Vue.js 模板)(当前版本的 pug 插件是在 HTML 范围内创建的,所以我们在这里使用解决方法)
    • 前缀:<template lang="pug">
    • 后缀:</template>
    • 放置模式:+ taggedString("pug")
  4. 点击“确定”和“应用”

原子

  1. 安装language-babellanguage-pug-jade
    我建议使用 language-pug-jade,因为它更适合我。 但是还有更多构建 pugjs 语法的方法:language-pugatom-pug,你也可以试试。
  2. 在atom中打开language-babel的设置
  3. 找到“JavaScript 标记模板文字语法扩展”下的字段
  4. 输入:pug:source.pug
    更多细节:gandm/language-babel#javascript-tagged-template-literal-grammar-extensions
  5. 重启原子

视觉工作室代码

  1. 打开扩展设置
  2. 在搜索栏中搜索“vscode-react-pug
  3. 点击“安装”和“重新加载”
  4. 如果您使用默认语法以外的任何语法(例如非常流行的 Babel JavaScript),您可能需要添加对 Atom 语法的支持([Microsoft/vscode-js-atom-grammar](https://marketplace.visualstudio .com/items?itemName=ms-vscode.js-atom-grammar))。

查看除此之外的历史:kaminaly/vscode-react-pug#4