JSX 是 createElement 的语法糖

JSX 经过编译,变成 React.createElement 调用形式

App1JSX是createElement的语法糖.jsx

class App extends React.Component {
  render() {
    return (
      // <div id="J_Box" className="box">
      //   <h1 className="title">
      //     This is a <span>TITLE</span>
      //   </h1>
      // </div>
      React.createElement(
        'div',
        {
          className: 'box',
          id: "J_Box"
        },
        React.createElement(
          'h1',
          {
            className: 'title'
          },
          'This is a ',
          React.createElement(
            'span',
            null,
            'TITLE'
          )
        )
      )
    )
  }
}
ReactDOM.render(<App />, document.getElementById('app'))

React 元素类型

App2React元素类型.jsx

class MyButton extends React.Component {
  render() {
    return (
      <button>Click</button>
    )
  }
}
class App extends React.Component {
  render() {
    return (

      /**
       * React 元素类型
       * MyButton -> React 元素
       * 用到了一个 JSX 的组件,那么这个组件必须存在在当前模块的作用域中
       * React 通过编译 JSX,将其转为 React.createElement 调用形式
       *    React 要使用 createElement ,就必须让 React 库存在在当前的模块作用域中
       *    开发环境: import React from 'react';
       *    生产环境: 在 index.html 的 script 的 src 中引入 React CDN
       *             不需要 import React ,因为此时 React 是挂载到全局的
       */
      <MyButton />
    )
  }
}
ReactDOM.render(<App />, document.getElementById('app'))

使用点语法

App3使用点语法.jsx

const colorSystem = {
  'success': 'green',
  'primary': 'blue',
  'warning': 'orange',
  'danger': 'red'
}
const MyUI = {
  // 类组件
  Button: class extends React.Component {
    render() {
      const { type, children } = this.props
      return (
        <button
          style={{
            color: '#fff',
            backgroundColor: colorSystem[type]
          }}
        >{ children }</button>
      )
    }
  },
  // 函数组件
  input: function(props) {
    const { placeholder, changeValue } = props
    return (
      <input type="text"
        placeholder={ placeholder }
        onChange={ e => changeValue(e) } />
    )
  }
}
class App extends React.Component {
  changeValue(e) {
    console.log(e.target.value)
  }
  render() {
    return (
      <>
        <MyUI.Button type="danger">Click</MyUI.Button>
        <MyUI.input placeholder="请输入..." changeValue={ this.changeValue.bind(this) }></MyUI.input>
      </>
    )
  }
}
ReactDOM.render(<App />, document.getElementById('app'))

书写规范

  1. 小写字母开头代表 HTML 的内置组件(<div><h1>
    1. 标签转换为 'div'、'h1' -> 作为 React.createElement 的第一个参数(React.createElement('div'))
  2. 大写字母开头的自定义组件 <MyButton />
    1. 编辑为 React.createElement(MyButton)

运行时选择 React 类型

App4运行时才选择React组件类型.jsx

class LoginBtnGroup extends React.Component {
  render() {
    return (
      <div>
        <button>登录</button>
        <button>注册</button>
      </div>
    )
  }
}
class WelcomeInfo extends React.Component {
  render() {
    return (
      <div>
        <h1>欢迎您, { this.props.username }</h1>
      </div>
    )
  }
}
class Header extends React.Component {
  static components = {
    'login': LoginBtnGroup,
    'welcome': WelcomeInfo
  }
  render() {
    const HeaderUser = Header.components[this.props.type]
    return (
      // <components[this.props.type] { ...this.props } /> // 这样写会报错
      <HeaderUser { ...this.props } />
    )
  }
}
class App extends React.Component {
  render() {
    return (
      <Header
        type="welcome"
        username="Lance"
      />
    )
  }
}
ReactDOM.render(<App />, document.getElementById('app'))

JSX 中的 props

Props