React - 使用JSX从ES6模板文字动态创建标记

时间:2017-01-13 09:46:01

标签: reactjs babeljs template-strings

我需要在React render方法中显示一个header元素,其中级别是在构造函数中动态设置的:



class HeaderComponent extends React.Component {

    constructor(props){
        super(props);
        
        this._checkedDepth = Math.min(6, props.depth)
    }

    render(){
        return(<h{ this._checkedDepth }>{ this.props.name }</h{ this._checkedDepth }>)
    }
}

ReactDOM.render(
  <HeaderComponent name="Header 1" depth="2"/>,
  document.getElementById('app')
);
&#13;
<div id="app"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
&#13;
&#13;
&#13;

这应该使用<h2>Header 1</h2>name="Header 1"呈现depth=2,但我收到错误:

  

未捕获错误:找不到模块&#34; ./ HeaderComponent&#34;

我在俯瞰什么?

我正在使用React 15.4.1babel-preset-es2015 6.9.0babel-preset-react 6.5.0并在Chrome 55中运行它。

2 个答案:

答案 0 :(得分:3)

  

每个JSX元素只是用于调用的语法糖   React.createElement(component,props,... children)。那么,你有什么   可以用简单的JavaScript完成JSX。 -   https://facebook.github.io/react/docs/react-without-jsx.html

所以你可以这样做:

render() {
  return React.createElement(`h${this._checkedDepth}`, this.props)
}

答案 1 :(得分:1)

可能有点太晚了,但你可以动态创建一个组件或标签而不使用React.createClass和JSX将标签名称放在变量中,并像使用任何其他组件一样使用该变量。

在你的情况下,在render内,你应该有:

const TitleTag = `h{ this._checkedDepth }>`;

return <TitleTag>{ this.props.name }</TitleTag>

请注意,该变量的第一个字符必须为大写,以便让React知道&#39; sa反应组件,否则将插入与变量完全相同的名称(非值)的标记。

请参阅https://reactjs.org/docs/jsx-in-depth.html#user-defined-components-must-be-capitalized

  

当元素类型以小写字母开头时,它引用a   内置组件,例如<div><span>,并生成字符串'div'   或'span'传递给React.createElement。以a开头的类型   大写字母如<Foo />编译为React.createElement(Foo)和   对应于JavaScript文件中定义或导入的组件。

     

我们建议使用大写字母命名组件。如果你有   以小写字母开头的组件,将其分配给a   在JSX中使用它之前的大写变量。

如果没有创建该变量,就无法做到这一点,因此尝试像在代码中一样动态执行此操作(编译器限制)。

这是一个完整的例子:

&#13;
&#13;
class HeaderComponent extends React.Component {

  constructor(props) {
    super(props);
    
    const depth = Math.max(Math.min(parseInt(props.depth) || 1, 6), 1);
    
    this.state = { depth };
  }

  onClick() {
    let depth;
    
    do {
      depth = Math.floor(Math.random() * 6) + 1;
    } while(depth === this.state.depth);
    
    this.setState({ depth });
  }

  render() {    
    const Title = `h${ this.state.depth }`;
  
    return <Title className="title" onClick={ () => this.onClick() }>{ this.props.name }</Title>;
  }
}

ReactDOM.render(
  <HeaderComponent name="Click Me!" depth="1"/>,
  document.getElementById('app')
);
&#13;
body { margin: 0; }

h1 { font-size: 4rem; }
h2 { font-size: 3.5rem; }
h3 { font-size: 3rem; }
h4 { font-size: 2.5rem; }
h5 { font-size: 2rem; }
h6 { font-size: 1.5rem; }

.title {
  margin: 0;
  padding: 0 .5rem;
  cursor: pointer;
  user-select: none;
}

.title:hover {
  background: #FFA;
}
&#13;
<div id="app"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
&#13;
&#13;
&#13;