React 学习笔记(一)-- 基础知识以及 jsx语法

568 阅读9分钟

先附上React官网中文版 & React官网英文版有很多问题都要通过查询官方文档来解决,要学会查文档

GitHub:React 源码+笔记

一、React 简介

1. 关于 React

整几个面试题来认识一下~~

什么是 React ?

React 是一个用于构建用户界面的 JavaScript 库。

  • 是一个将数据渲染为 HTML 视图的开源 JS 库
  • 它遵循基于组件的方法,有助于构建可重用的 UI 组件
  • 它用于开发复杂的交互式的 web 和移动 UI

React 有什么特点?

  1. 使用虚拟 DOM ,不总是直接操作页面真实DOM
  2. 它可以用服务器渲染
  3. 它遵循单向数据流或数据绑定
  4. 高效
  5. 声明式编码,组件化编码

React 的一些主要优点?

  1. 它提高了应用的性能
  2. 可以方便在客户端和服务器端使用
  3. 由于使用 JSX,代码的可读性更好
  4. 使用React,编写 UI 测试用例变得非常容易

什么是声明式编程?

虚拟DOM帮助我们从命令式编程转到了声明式编程的模式, React官方的说法:Virtual DOM 是一种编程理念。 在这个理念中,UI以一种理想化或者说虚拟化的方式保存在内存中,并且它是一个相对简单的JavaScript对象 我们可以通过ReactDOM.render让 虚拟DOM 和 真实DOM同步起来,这个过程中叫做协调(Reconciliation);

这种编程的方式赋予了React声明式的API

  • 你只需要告诉React希望让UI是什么状态;
  • React来确保DOM和这些状态是匹配的;
  • 你不需要直接进行DOM操作,只可以从手动更改DOM、属性操作、事件处理中解放出来

2. Hello React

我们在编写React代码时,有三个依赖都是必不可少的:

  • React 核心库
  • 操作 DOM 的 react 扩展库
  • 将 jsx 转为 js 的 babel 库 引入方式:
  • 方式一:直接CDN引入
  • 方式二:下载后,添加本地依赖
  • 方式三:通过npm管理(后续脚手架再使用)
//这里有一个crossorigin的属性,这个属性的目的是为了拿到跨域脚本的错误信息
<!-- 准备好一个“容器” -->
<div id="test"></div>
<!-- 引入react核心库,放在第一个-->
 <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<!-- 引入react-dom,用于支持react操作DOM -->
  <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel"> /* 此处一定要写babel ---jsx*/
    //1.创建虚拟DOM
   const VDOM = <h1>Hello,React</h1> /* 此处一定不要写引号,因为不是字符串 */
    // const VDOM = '<h1>Hello,React</h1> 加入单引号h1标签失效
    //2.渲染虚拟DOM到页面
    // ReactDOM.render(虚拟DOM,容器)
   ReactDOM.render(VDOM, document.getElementById('test'))
</script>

ReactDOM.render函数

  • 参数一:传递要渲染的内容,这个内容可以是HTML元素,也可以是React的组件 , 这里我们传入了一个h1元素,后面我们就会使用React组件
  • 参数二:将渲染的内容,挂载到哪一个HTML元素上 ,这里我们已经提定义一个id为app的div

3. 虚拟 DOM 和真实 DOM 的两种创建方法

关于虚拟DOM: 1.本质是Object类型的对象(一般对象) 2.虚拟DOM比较“轻”(即内部属性少),真实DOM比较“重”(即内部属性多),因为虚拟DOM是React内部在用,无需真实DOM上那么多的属性。 3.虚拟DOM最终会被React转化为真实DOM,呈现在页面上。

1. JS 创建虚拟 DOM

如果标签内部还有标签,则会再次使用React.createElement,十分繁琐,这里只是一个简单的实例,具体解释在下方

<!-- 准备好一个“容器” -->
<div id="test">这里原本的内容会被覆盖掉</div>
<script type="text/javascript">
    //1.创建虚拟DOM
    // const VDOM = React.createElement(标签名,标签属性,标签内容)
    const VDOM = React.createElement('h1', { id: 'title' }, React.createElement('span', {}, 'Hello,React'))
    //2.渲染虚拟DOM到页面
    ReactDOM.render(VDOM, document.getElementById('test'))
</script>

2. Jsx 创建虚拟DOM

<!-- 准备好一个“容器” -->
<div id="test"></div>

<script type="text/babel" > /* 此处一定要写babel */
        //1.创建虚拟DOM
        const VDOM = (  /* 此处一定不要写引号,因为不是字符串 */
                <h1 id="title">
                        <span>Hello,React</span>
                </h1>
        )
        //2.渲染虚拟DOM到页面
ReactDOM.render(VDOM,document.getElementById('test'))
</script>

js 的写法并不是常用的,常用jsx来写,毕竟JSX更符合书写的习惯

二、jsx 语法

1. 全称:  JavaScript XML

2. react定义的一种类似于XML的JS扩展语法: JS + XML本质是React . createElement ( component , props , ... children ) 方法的语法糖

3. 作用: 用来简化创建虚拟DOM

1) 写法: var ele = <h1>Hello JSX!</h1>

2) 注意1:它不是字符串, 也不是HTML/XML标签

3) 注意2:它最终产生的就是一个JS对象

1. 语法规则:

  1. 定义虚拟DOM,不能使用""
  2. 标签中混入JS表达式的时候使用{} ,js语句不能放入{}
  3. 样式的类名指定不能使用class,使用className
  4. 内联样式要使用{{}}包裹
  5. 不能有多个根标签,只能有一个根标签
  6. 标签必须闭合,自闭合也行,即如果是单标签,必须以 / 结尾
  7. 如果小写字母开头,就将标签转化为 html 同名元素,如果 html 中无该标签对应的元素,就报错;如果是大写字母开头,react 就去渲染对应的组件,如果没有就报错
  8. 为了方便阅读,我们通常在jsx的外层包裹一个小括号(),这样可以方便阅读,并且jsx可以进行换行书写
<style>
    .title {
        background-color: orange;
        width: 200px;
    }
</style>
        
<script type="text/babel">
    const myId = 'aTgUiGu'
    const myData = 'HeLlo,rEaCt'

    //1.创建虚拟DOM
    const VDOM = (
        <div>
            <h2 className="title" id={myId.toLowerCase()}>
                    <span style={{ color: 'white', fontSize: '29px' }}>{myData.toLowerCase()}</span>
            </h2>
            <h2 className="title" id={myId.toUpperCase()}>
                    <span style={{ color: 'white', fontSize: '29px' }}>{myData.toLowerCase()}</span>
            </h2>
            <input type="text" />
        </div>
    )
    //2.渲染虚拟DOM到页面
    ReactDOM.render(VDOM, document.getElementById('test'))
  </script>

1. 注释

写在花括号里

ReactDOM.render(
    <div>
    <h1>小丞</h1>
    {/*注释...*/}
     </div>,
    document.getElementById('example')
);

2. jsx嵌入数据

  • 情况一:当变量是Number、String、Array类型时,可以直接显示 ,数组自动展开全部成员
  • 情况二:当变量是null、undefined、Boolean类型时,内容为空; 如果希望可以显示null、undefined、Boolean,那么需要转成字符串; 转换的方式有很多,比如toString方法、和空字符串拼接,String(变量)等方式;
  • 情况三:对象类型不能作为子元素(not valid as a React child
<script type="text/babel">
      class App extends React.Component {
        constructor() {
          super();

          this.state = {
            // 1.在{}中可以正常显示显示的内容
            name: "why", // String
            age: 18, // Number
            names: ["zgc", "wf"], // Array

            // 2.在{}中不能显示(忽略)
            test1: null, // null
            test2: undefined, // undefined
            test3: true, // Boolean
            flag: true,

            // 3.对象不能作为jsx的子类,报错
            // friend: {
            //   name: "kobe",
            //   age: 40,
            // },
          };
        }

        render() {
          return (
            <div>
              <h2>{this.state.name}</h2>
              <h2>{this.state.age}</h2>
              <h2>{this.state.names}</h2>
              {/*不显示*/}
              <h2>{this.state.test1}</h2>
              <h2>{this.state.test2}</h2>
              <h2>{this.state.test3}</h2>
              {/*显示*/}
              <h2>{this.state.test1 + ""}</h2>
              <h2>{this.state.test2 + ""}</h2>
              <h2>{this.state.test3.toString()}</h2>

              <h2>{this.state.flag ? "你好啊" : null}</h2>

              <h2>{this.state.friend}</h2>
            </div>
          );
        }
      }

      ReactDOM.render(<App />, document.getElementById("app"));
    </script>

1640160008(1).png

2. tip: JSX 小练习

一定注意区分:【js语句(代码)】与【js表达式】

1.表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方
    下面这些都是表达式:
                    (1). a
                    (2). a+b
                    (3). demo(1)
                    (4). arr.map() 
                    (5). function test () {}
                    (6)三元运算符 
                    (7)执行一个函数
2.语句(代码):
        下面这些都是语句(代码):
                    (1).if(){}
                    (2).for(){}
                    (3).switch(){case:xxxx}

根据动态数据生成 li

const data = ['A','B','C']
const VDOM = (
    <div>
        <ul>
            {
            //不能放js语句,只能写js表达式
                data.map((item,index)=>{
                    return <li key={index}>{item}</li>
                })
            }
        </ul>
    </div>
)
ReactDOM.render(VDOM,document.querySelector('.test'))
<script type="text/babel">
  class App extends React.Component {
    constructor(props) {
      super(props);

      this.state = {
        firstname: "zhang",
        lastname: "bryant",
        isLogin: false,
      };
    }

    render() {
      const { firstname, lastname, isLogin } = this.state;

      return (
        <div>
          {/*1.运算符表达式*/}
          <h2>{firstname + " " + lastname}</h2>
          <h2>{20 * 50}</h2>

          {/*2.三元表达式*/}
          <h2>{isLogin ? "欢迎回来~" : "请先登录~"}</h2>

          {/*3.进行函数调用*/}
          <h2>{this.getFullName()}</h2>
        </div>
      );
    }

    getFullName() {
      return this.state.firstname + " " + this.state.lastname;
    }
  }

  ReactDOM.render(<App />, document.getElementById("app"));
</script>

案例1:

<!-- 2.编写React代码 -->
<script type="text/babel">
  class App extends React.Component {
    constructor() {
      super();

      this.state = {
        message: "Hello World",
        movies: ["大话西游", "盗梦空间", "星际穿越", "流浪地球"],
      };
    }

    render() {
      const liArray = [];
      for (let movie of this.state.movies) {
        liArray.push(<li>{movie}</li>);
      }

      return (
        <div>
          <h2>电影列表1</h2>
          <ul>{liArray}</ul>

          <h2>电影列表2</h2>
          <ul>
            {this.state.movies.map((item) => {
              return <li>{item}</li>;
            })}
          </ul>
        </div>
      );
    }
  }

  ReactDOM.render(<App />, document.getElementById("app"));
</script>

1640157353(1).png

案例2:

<script type="text/babel">
  class App extends React.Component {
    constructor() {
      super();

      this.state = {
        counter: 0,
      };
    }

    render() {
      return (
        <div>
          <h2>当前计数: {this.state.counter}</h2>
          <button onClick={this.increment}>+1</button>
          <button onClick={this.decrement.bind(this)}>-1</button>
          <img src="" alt="" />
        </div>
      );
    }

    increment = () => {
      this.setState({
        counter: this.state.counter + 1,
      });
    };

    decrement() {
      this.setState({
        counter: this.state.counter - 1,
      });
    }
  }

  ReactDOM.render(<App />, document.getElementById("app"));
</script>

1640158290(1).png

3. jsx绑定属性

  • 比如元素都会有title属性
  • 比如img元素会有src属性
  • 比如a元素会有href属性
  • 比如元素可能需要绑定class
  • 比如原生使用内联样式style 注意

绑定style内联样式--有两个大括号 {{}}, 第一个表示里面的内容为js表达式,第二个表示里面的内容为一个对象,key:value格式,key采用小驼峰命名,value写字符串,如果去掉引号为变量

<script type="text/babel">
  class App extends React.Component {
    constructor() {
      super();

      this.state = {
        title: "标题",
        imgUrl:
          "http://p2.music.126.net/L8IDEWMk_6vyT0asSkPgXw==/109951163990535633.jpg",
        link: "http://www.baidu.com",
        active: true,
      };
    }
    // 封装方法:图片地址后加参数控制图片大小
    getSizeImage(imgUrl, size) {
      // 参数控制图片大小
      return imgUrl + `?param=${size}x${size}`;
    }

    render() {
      const { title, imgUrl, link, active } = this.state;
      return (
        <div>
          {/* 1.绑定普通属性 */}
          <h2 title={title}>我是标题</h2>
          <img src={this.getSizeImage(imgUrl, 140)} alt="" />
          <hr />
          <a href={link} target="_blank">
            百度一下
          </a>

          {/* 2.绑定class */}
          <div className="box title">我是div元素</div>
          <div className={"box title " + (active ? "active" : "")}>
            我也是div元素
          </div>
          <label htmlFor=""></label>

          {/* 3.绑定style {{ ... }}*/}
          <div style={{ color: "red", fontSize: "10px" }}>
            我是div,绑定style属性
          </div>
        </div>
      );
    }
  }

  ReactDOM.render(<App />, document.getElementById("app"));
</script>

1640164935(1).png

4. React事件绑定

如果原生DOM原生有一个监听事件,我们可以如何操作呢?

  • 方式一:获取DOM原生,添加监听事件;
  • 方式二:在HTML原生中,直接绑定onclick; 在React中是如何操作呢?

我们来实现一下React中的事件监听,这里主要有两点不同 :

  • React 事件的命名采用小驼峰式(camelCase),而不是纯小写;
  • 我们需要通过{}传入一个事件处理函数,这个函数会在事件发生时被执行;

1. this的绑定问题

在事件执行后,我们可能需要获取当前类的对象中相关的属性,这个时候需要用到this ,如果我们这里直接打印this,也会发现它是一个undefined .

为什么是undefined呢?

原因是btnClick函数并不是我们主动调用的,而且当button发生改变时,React内部调用了btnClick函数; 而它内部调用时,并不知道要如何绑定正确的this;

如何解决this的问题呢?

  • 方案一:bind给btnClick显示绑定this
  • 方案二:使用 ES6 class fields 语法
  • 方案三:事件监听时传入箭头函数(推荐)
<script type="text/babel">
  class App extends React.Component {
    constructor() {
      super();
      this.state = {
        message: "你好啊",
        counter: 100,
      };

      this.btnClick = this.btnClick.bind(this);
    }

    render() {
      return (
        <div>
          {/* 1.方案一: bind绑定this(显示绑定) */}
          <button onClick={this.btnClick}>按钮1</button>

          {/* 2.方案二: 定义函数时, 使用箭头函数 */}
          <button onClick={this.increment}>+1</button>

          {/* 2.方案三(推荐): 直接传入一个箭头函数, 在箭头函数中调用需要执行的函数*/}
          <button
            onClick={() => {
              {
                /*这里箭头函数的this为render里的this*/
              }
              this.decrement("why");
            }}
          >
            -1
          </button>
        </div>
      );
    }

    btnClick() {
      console.log(this.state.message);
    }

    // 箭头函数中永远不绑定this
    // ES6中给对象增加属性: class fields
    increment = () => {
      console.log(this.state.counter);
    };

    decrement(name) {
      console.log(this.state.counter, name);
    }
  }

  ReactDOM.render(<App />, document.getElementById("app"));
</script>

2. 事件参数传递

在执行事件函数时,有可能我们需要获取一些参数信息:比如event对象、其他参数

  • 情况一:获取event对象 : 很多时候我们需要拿到event对象来做一些事情(比如阻止默认行为) 假如我们用不到this,那么直接传入函数就可以获取到event对象;
  • 情况二:获取更多参数 :有更多参数时,我们最好的方式就是传入一个箭头函数,主动执行的事件函数,并且传入相关的其他参数
<script type="text/babel">
  class App extends React.Component {
    constructor() {
      super();

      this.state = {
        movies: ["大话西游", "海王", "流浪地球", "盗梦空间"],
      };

      this.btnClick = this.btnClick.bind(this);
    }

    render() {
      return (
        <div>
          <button onClick={this.btnClick}>按钮</button>

          <ul>
            {/*this.state.movies.map((每一项数据, 索引值, 整个数组)*/}

            {this.state.movies.map((item, index, arr) => {
              return (
                <li
                  onClick={(e) => {
                    this.liClick(item, index, e);
                  }}
                >
                  {item}
                </li>
              );
            })}
          </ul>
        </div>
      );
    }
    // 默认帮你传入event
    btnClick(event) {
      console.log("按钮发生了点击", event);
    }

    liClick(item, index, event) {
      console.log("li发生了点击", item, index, event);
    }
  }

  ReactDOM.render(<App />, document.getElementById("app"));
</script>

5. React条件渲染

某些情况下,界面的内容会根据不同的情况显示不同的内容,或者决定是否渲染某部分内容:

  • 在vue中,我们会通过指令来控制:比如v-if、v-show;
  • 在React中,所有的条件判断都和普通的JavaScript代码一致; 常见的条件渲染的方式有哪些呢?
  • 方式一:条件判断语句 适合逻辑较多的情况
  • 方式二:三元运算符 适合逻辑比较简单
  • 方式三: && 适合如果条件成立,渲染某一个组件;如果条件不成立,什么内容也不渲染
<script type="text/babel">
  class App extends React.Component {
    constructor(props) {
      super(props);

      this.state = {
        isLogin: true,
      };
    }

    render() {
      const { isLogin } = this.state;

      // 1.方案一:通过if判断: 逻辑代码非常多的情况
      let welcome = null;
      if (isLogin) {
        welcome = <h2>欢迎回来~</h2>;
      } else {
        welcome = <h2>请先登录~</h2>;
      }

      return (
        <div>
          {welcome}

          {/* 2.方案二: 三元运算符 */}
          <button onClick={(e) => this.loginClick()}>
            {isLogin ? "退出" : "登录"}
          </button>

          <hr />

          <h2>{isLogin ? "你好啊, zgc" : null}</h2>

          {/* 3.方案三: 逻辑与&& */}
          {/* 逻辑与: 一个条件不成立, 后面的条件都不会进行判断了,
          如果前面的条件都为真,则将最后面条件的结果作为整个表达式的结果返回出去 */}
          <h2>{isLogin && "你好啊, zgc"}</h2>
          
          {/*上下这两个的区别为当isLogin为false时h2标签是否渲染*/}
          
          {isLogin && <h2>你好啊, zgc</h2>}
        </div>
      );
    }

    loginClick() {
      this.setState({
        isLogin: !this.state.isLogin,
      });
    }
  }

  ReactDOM.render(<App />, document.getElementById("app"));
</script>

1. React实现 v-show的效果

主要是控制display属性是否为none

<script type="text/babel">
  class App extends React.Component {
    constructor(props) {
      super(props);

      this.state = {
        isLogin: true,
      };
    }

    loginClick() {
      this.setState({
        isLogin: !this.state.isLogin,
      });
    }

    render() {
      const { isLogin } = this.state;
      return (
        <div>
          <button onClick={(e) => this.loginClick()}>
            {isLogin ? "退出" : "登录"}
          </button>
          {/*React实现v-show*/}
          <h2 style={{ display: isLogin ? "block" : "none" }}>
            你好啊, coderwhy
          </h2>
        </div>
      );
    }
  }

  ReactDOM.render(<App />, document.getElementById("app"));
</script>

6. React列表渲染--高阶函数

很多时候我们在展示一个数组中的数据之前,需要先对它进行一些处理:

  • 比如过滤掉一些内容:filter函数
  • 比如截取数组中的一部分内容:slice函数
<script type="text/babel">
class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      names: ["abc", "cba", "nba", "mba", "dna"],
      numbers: [110, 123, 50, 32, 55, 10, 8, 333]
    }
  }

  render() {
    return (
      <div>
        <h2>名字列表</h2>
        <ul>
          {
            this.state.names.map(item => {
              return <li>{item}</li>
            })
          }
        </ul>

        <h2>数字列表(过滤)</h2>
        <ul>
          {
            this.state.numbers.filter(item => {
              return item >= 50;
            }).map(item => {
              return <li>{item}</li>
            })
          }
        </ul>

        <h2>数字列表(过滤简写)</h2>
        <ul>
          {
            this.state.numbers.filter(item => item >= 50).map(item => <li>{item}</li>)
          }
        </ul>

        <h2>数字列表(截取)</h2>
        <ul>
          {
          //截取前4条数据 0,1,2,3
            this.state.numbers.slice(0, 4).map(item => {
              return <li>{item}</li>
            })
          }
        </ul>
      </div>
    )
  }
}

ReactDOM.render(<App />, document.getElementById("app"));
</script>

三、 jsx的本质-源码

实际上,jsx 仅仅只是 React.createElement(component, props, ...children) 函数的语法糖, 所有的jsx最终都会被转换成React.createElement的函数调用。

createElement需要传递三个参数

  • 参数一:type 当前ReactElement的类型;如果是标签元素,那么就使用字符串表示 “div”; 如果是组件元素,那么就直接使用组件的名称;
  • 参数二:config 所有jsx中的属性都在config中以对象的属性和值的形式存储
  • 参数三:children 存放在标签中的内容,以children数组的方式进行存储;当然,如果是多个元素呢?React内部有对它们进行处理,处理的源码在下方
const message1 = <h2>Hello React</h2>; // jsx -> babel -> React.createElement()
const message2 = React.createElement("h2", null, "Hello React");
<!-- 准备好一个“容器” -->
<div id="test">这里原本的内容会被覆盖掉</div>
<script type="text/javascript">
    //1.创建虚拟DOM
    // const VDOM = React.createElement(标签名,标签属性,标签内容)
    const VDOM = React.createElement('h1', { id: 'title' }, React.createElement('span', {}, 'Hello,React'))
    //2.渲染虚拟DOM到页面
    ReactDOM.render(VDOM, document.getElementById('test'))
</script>

//JSX代码
const VDOM = ( 
   <h1 id="title"> <span>Hello,React</span> </h1> 
 )

1. 源码:

React.createElement在源码的什么位置呢
Github React源码下载:github.com/facebook/re…

1640241417(1).png

export function createElement(type, config, children) {
  let propName;

  // Reserved names are extracted
  const props = {};

  let key = null;
  let ref = null;
  let self = null;
  let source = null;

  if (config != null) {
    if (hasValidRef(config)) {
      ref = config.ref;

      if (__DEV__) {
        warnIfStringRefCannotBeAutoConverted(config);
      }
    }
    if (hasValidKey(config)) {
      if (__DEV__) {
        checkKeyStringCoercion(config.key);
      }
      key = '' + config.key;
    }

    self = config.__self === undefined ? null : config.__self;
    source = config.__source === undefined ? null : config.__source;
    // Remaining properties are added to a new props object
    for (propName in config) {
      if (
        hasOwnProperty.call(config, propName) &&
        !RESERVED_PROPS.hasOwnProperty(propName)
      ) {
        props[propName] = config[propName];
      }
    }
  }

  // Children can be more than one argument, and those are transferred onto
  // the newly allocated props object.
  const childrenLength = arguments.length - 2;
  if (childrenLength === 1) {
    props.children = children;
  } else if (childrenLength > 1) {
    const childArray = Array(childrenLength);
    for (let i = 0; i < childrenLength; i++) {
      childArray[i] = arguments[i + 2];
    }
    if (__DEV__) {
      if (Object.freeze) {
        Object.freeze(childArray);
      }
    }
    props.children = childArray;
  }

  // Resolve default props
  if (type && type.defaultProps) {
    const defaultProps = type.defaultProps;
    for (propName in defaultProps) {
      if (props[propName] === undefined) {
        props[propName] = defaultProps[propName];
      }
    }
  }
  if (__DEV__) {
    if (key || ref) {
      const displayName =
        typeof type === 'function'
          ? type.displayName || type.name || 'Unknown'
          : type;
      if (key) {
        defineKeyPropWarningGetter(props, displayName);
      }
      if (ref) {
        defineRefPropWarningGetter(props, displayName);
      }
    }
  }
  return ReactElement(
    type,
    key,
    ref,
    self,
    source,
    ReactCurrentOwner.current,
    props,
  );
}

2. babel的官网中查看转换

我们知道默认jsx是通过babel帮我们进行语法转换的,所以我们之前写的jsx代码都需要依赖babel。 可以在babel的官网中快速查看转换的过程:babeljs.io/repl/#?pres…

  <script type="text/babel">
    class App extends React.Component {
      constructor(props) {
        super(props);

        this.state = {
          
        }
      }

      render() {
        return (
          <div>
            <div className="header">
              <h1 title="标题">我是标题</h1>
            </div>
            <div className="content">
              <h2>我是页面的内容</h2>
              <button>按钮</button>
              <button>+1</button>
              <a href="http://www.baidu.com">百度一下</a>
            </div>
            <div className="footer">
              <p>我是尾部的内容</p>
            </div>
          </div>
        )
      }
    }

    ReactDOM.render(<App/>, document.getElementById("app"));
  </script>

转换成 React.createElement("h2", null, header,content,footer...)格式

 <script type="text/babel">
    class App extends React.Component {
      constructor(props) {
        super(props);

        this.state = {

        }
      }

      render() {
        return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
          className: "header"
        }, /*#__PURE__*/React.createElement("h1", {
          title: "\u6807\u9898"
        }, "\u6211\u662F\u6807\u9898")), /*#__PURE__*/React.createElement("div", {
          className: "content"
        }, /*#__PURE__*/React.createElement("h2", null, "\u6211\u662F\u9875\u9762\u7684\u5185\u5BB9"), /*#__PURE__*/React.createElement("button", null, "\u6309\u94AE"), /*#__PURE__*/React.createElement("button", null, "+1"), /*#__PURE__*/React.createElement("a", {
          href: "http://www.baidu.com"
        }, "\u767E\u5EA6\u4E00\u4E0B")), /*#__PURE__*/React.createElement("div", {
          className: "footer"
        }, /*#__PURE__*/React.createElement("p", null, "\u6211\u662F\u5C3E\u90E8\u7684\u5185\u5BB9")));
      }
    }

    ReactDOM.render(<App />, document.getElementById("app"));
  </script>