JSX 本质

点击查看【codepen】
编译后的内容

  1. class App extends React.Component {
  2. render() {
  3. return /*#__PURE__*/ React.createElement(
  4. 'div',
  5. { className: 'box', id: 'J_Box' } /*#__PURE__*/,
  6. React.createElement(
  7. 'h1',
  8. { className: 'title' },
  9. 'This is a ' /*#__PURE__*/,
  10. React.createElement('span', null, 'TITLE')
  11. )
  12. );
  13. }
  14. }
  15. ReactDOM.render(
  16. /*#__PURE__*/ React.createElement(App, null),
  17. document.getElementById('app')
  18. );

React.createElement(标签,{标签属性},…子元素)

JSX 其实是 React.createElement 函数调用的语法糖
React 会把 JSX 编译为 React.createElement 调用形式

React 元素类型

  1. class MyButton extends React.Component{
  2. render(){
  3. return <button>Click</button>;
  4. }
  5. }

这个 MyButton 就是 React 元素,并且也是 React 元素类型
组件内使用 JSX,这个组件必须存在当前模块的作用域中

  • 如在其它文件中,就使用 export / import 导出到使用的作用域

因为 React 编译 JSX 变为 React.createElement 调用形式,而要使用到 React 下的 createElement,那么要让 React 库存在当前的模块作用域中

  • 在工程化时要 import React from 'react'
  • 生产时是在 index.html 的 script 属性 src 来引用 React CDN
    所以不需要 import React
    React 是持载至全局 window.React 能访问到

    如何在 JSX 中使用点语法

    点击查看【codepen】

    JSX 书写规范

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

    运行时选择 React 类型

    点击查看【codepen】

    JSX 的 props

    表达式
    JSX 中的大括号 {} 里面可以传入任何 JavaScript 表达式

    if, for, switch, function 这些是语句,非表达式可以在 JSX 外面使用

  1. class App extends React.Component {
  2. state = {
  3. mainTitle: "This is a MAINTITLE",
  4. subTitle: "This is a SUBTITLE",
  5. titleShow: "main"
  6. };
  7. render() {
  8. // 非表达式在 JSX 外面使用
  9. if (this.state.titleShow == "sub") {
  10. title = <h2>{this.state.subTitle}</h2>;
  11. } else {
  12. title = <h1>{this.state.mainTitle}</h1>;
  13. }
  14. return <div>{title}</div>;
  15. // 或者写在 JSX 里面传入 JS 表达式,使用三目运算符
  16. return
  17. (
  18. <div>
  19. { titleShow === "sub" ? <h2>{subTitle}</h2> : <h1>{mainTitle}</h1> }
  20. </div>
  21. );
  22. }
  23. }

字面量字符串的注意

  1. // 这是字符串字面量
  2. <MyTitle title="这是一个标题" author="小野" />
  3. // 这是表达式
  4. <MyTitle title={"这是一个标题"} author={"小野"} />

JS表达式方式传入 props,HTML实体字符会被转义为普通字符
而字符串字面量传入 props 的方式不会对 HTML实体转义

  1. <MyTitle title="这是一个<字符串字面量>" author={"&lt;表达式&gt;"} /> // => 这是一个<字符串字面量> &lt;表达式&gt;
  2. <MyTitle title="这是一个&lt;字符串字面量&gt;" author={"<表达式>"} /> // => 这是一个<字符串字面量> <表达式>

props 的 bool 表达
authorShow="true",这是字符串传入的意义是字符串的意思,不代表 Bool 真假,字符串 true 是逻辑真
authorShow={true},Bool true 的意义代表 Bool 真假
authorShow, 不填值属性默认就是 Bool 真,但不推荐这么做因为语义不好

props 属性展开操作

  1. class App extends React.Component {
  2. render() {
  3. // 排除不要的 props
  4. const { abc, ...others } = this.props;
  5. return (
  6. <div>
  7. {/* props 属性展开操作 */}
  8. <MyTitle {...others} />
  9. </div>
  10. );
  11. }
  12. }
  13. ReactDOM.render(
  14. <App title="This is a TITLE" author="xiaoye" authorShow={true} abc={123} />,
  15. document.getElementById("app")
  16. );

点击查看【codepen】

JSX 子元素

注释
{/* */}

字符串字面量 不转义

  1. 去掉首尾空格换行
  2. 字符串之间的多个空格压缩为一个空格 ( )
  3. 字符串之间的换行压缩为一个空格(

JSX 作为 JSX 的子元素
可以用数组返回多个元素

null, undefined, bool 都是可以作为 JSX 的子元素,这些子元素是会被忽略不会渲染,为解决条件渲染的问题
标签是会渲染
点击查看【codepen】

JSX 函数子元素

JSX 的 props.children 跟 props 本身是有一致的特性
props.children 可以传递任何类型的子元素
点击查看【codepen】

  1. const Http = {
  2. Get: class extends React.Component {
  3. async componentDidMount() {
  4. const result = await axios(this.props.url);
  5. this.setState(
  6. {
  7. data: result.data,
  8. },
  9. () => {
  10. this.setState({
  11. component: this.props.children(this.state.data),
  12. }, 1000);
  13. }
  14. );
  15. }
  16. state = {
  17. data: [],
  18. component: this.props.loading || 'Loading...',
  19. };
  20. render() {
  21. return this.state.component;
  22. }
  23. },
  24. };
  25. class App extends React.Component {
  26. render() {
  27. return (
  28. <table>
  29. <thead>
  30. <tr>
  31. <th>ID</th>
  32. <th>姓名</th>
  33. <th>年级</th>
  34. </tr>
  35. </thead>
  36. <tbody>
  37. <Http.Get
  38. url='http://localhost:8080/getStudents'
  39. loading={
  40. <tr>
  41. <td colSpan='3'>正在加载中...</td>
  42. </tr>
  43. }
  44. >
  45. {(data) => {
  46. return data.map((item) => (
  47. <tr key={item.id}>
  48. <td>{item.id}</td>
  49. <td>{item.name}</td>
  50. <td>{item.grade}</td>
  51. </tr>
  52. ));
  53. }}
  54. </Http.Get>
  55. </tbody>
  56. </table>
  57. );
  58. }
  59. }