5

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

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')
);
<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>

<h2>Header 1</h2>这应该用name="Header 1"and渲染depth=2,但我得到一个错误:

未捕获的错误:找不到模块“./HeaderComponent”

我在看什么?

我正在使用React 15.4.1,babel-preset-es2015 6.9.0babel-preset-react 6.5.0Chrome 55.

4

2 回答 2

4

每个 JSX 元素只是调用 React.createElement(component, props, ...children) 的语法糖。所以,你可以用 JSX 做的任何事情也可以用纯 JavaScript 来完成。- https://facebook.github.io/react/docs/react-without-jsx.html

所以你可以做这样的事情:

render() {
  return React.createElement(`h${this._checkedDepth}`, this.props)
}
于 2017-01-13T09:52:42.077 回答
4

也许有点太晚了,但是您可以动态创建组件或标签,而无需使用React.createClassJSX 将标签名称放入变量中,并像使用任何其他组件一样使用该变量。

在你的情况下, inside render,你应该有类似的东西:

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

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

请注意,该变量的第一个字符必须为大写,以便让 React 知道这是一个 React 组件,否则将插入一个与您的变量完全相同的名称(不是值)的标签。

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

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

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

如果不创建该变量,就无法做到这一点,因此尝试像在代码中那样动态地执行它是行不通的(编译器限制)。

这是一个完整的工作示例:

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')
);
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;
}
<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>

于 2017-12-19T22:48:40.550 回答