一. 使用 create-react-app 快速构建 React 开发环境

npm install -g create-react-app
create-react-app my-app
cd my-app/
npm start

你也可以直接使用 Staticfile CDN 的 React CDN 库,地址如下:

<script src="https://unpkg.com/react@16/umd/react.development.js"></script> 
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> 
<!-- 生产环境中不建议使用 --> 
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>

二. React打包

react-app-rewired使用

它的作用是用来帮助你重写react脚手架配置

react-app-rewired@2.x版本需要搭配customize-cra使用。

npm i react-app-rewired customize-cra --save-dev

在根目录下新建文件config-overrides.js文件

const {
    override,
    addDecoratorsLegacy,
    disableEsLint,
} = require("customize-cra");

module.exports = {
    webpack: override(
        addDecoratorsLegacy(),
        disableEsLint(),
    )
};

修改package.json文件

"scripts": {		
    "start": "react-app-rewired start",		
    "build": "react-app-rewired build",		
    "test": "react-app-rewired test",		
    "eject": "react-scripts eject"		
  },

打开src文件夹,里面有个index.js和app.js文件,其中index.js是主入口文件,app.js就是页面展示建议react组件,

三.  React路由

npm install react-router react-router-dom

在app.js中导入

import {		
  Switch,		
  HashRouter as Router,		
  // BrowserRouter as Router,		
  Route,		
  Link		
} from 'react-router-dom';

调用方法一

<Router>
    {/*只显示某一页的内容 http://localhost:3000/#/或http://localhost:3000/#/help*/}
    <Switch>
      <Route path="/" exact component={home} />
      <Route path="/help" component={help}/>
    </Switch>
</Router>

调用方法二

<Router>
        <div>
          <Route exact path="/" component={home}/>
          <Route path="/help" component={help}/>
        </div>
      </Router>

四. 创建组件Table.js

新建组件注意事项

1、Component作为一个组件引入了,不需要再执行React.Component

2、使用class继承,元素必须在render()方法里面返回

3、样式类名书写是className,不是class

4、一定要将组件导出export default componentName

5、react组件名必须大写字母开头

6、只能return一个根元素,不能return两个根元素,也就是说renturn的标签必须包裹在一个根标签里面,不能是两个同级标签

import React, { Component } from 'react'

class Table extends Component {
  render() {
    return (
      <table>
        <thead>
          <tr>
            <td>Name</td>
            <td>Job</td>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>李狗蛋</td>
            <td>程序猿</td>
          </tr>
          <tr>
            <td>王翠花</td>
            <td>攻城狮</td>
          </tr>
        </tbody>
      </table>
    )
  }
}
export default Table

组件写好后,在app.js里面引入组件并使用

<Router>
        <div>
          <Route exact path="/" component={home}/>
          <Route path="/help" component={help}/>
          <Table Head={Head}/>
        </div>
      </Router>

五,简单组件

通过class创建的组件可以称之为复杂组件,还可以创建简单组件,所谓的简单组件,其实用类似函数的方式声明组件,现在用简单组件把table的头部和躯体部分分别分离出来作为一个单独的小组件

简单组件跟复杂组件的区别之一就是简单组件不需要render()方法去置换一下return元素,直接返回react元素

// table.js
function TableHead(props) {
  return (
    <thead>
      <tr>
        <th>Name</th>
        <th>Job</th>
      </tr>
    </thead>
  )
}

function TableBody(props) {
  return (
    <tbody>
      <tr>
        <td>李狗蛋</td>
        <td>程序猿</td>
      </tr>
      <tr>
        <td>王翠花</td>
        <td>攻城狮</td>
      </tr>
    </tbody>
  )
}

调用

class Table extends Component {
  render() {
    return (
      <table>
        <TableHead />
        <TableBody />
      </table>
    )
  }
}

所有组件都是可以相互嵌套的,而且简单组件和复杂组件也是可以相互嵌套的,并没有的区别

六. 组件通信props

react中组件通信跟vue有点类似,是通过props来接收数据传递,不同的是:

1、数据是全局保存在props对象里面的,直接调用props对象就可以获取

2、数据传递也不需要通过v-bind来绑定参数,直接写即可,只不过传入参数使用{}包裹,而不是""

3、在简单函数里,props是作为一个参数传入的,所以直接通过props.key获取,但是在class里面,props是继承于Compoent,需要通过super()方法,调用是通过this.props.key

因为所有组件都是在app.js里面渲染的,所以现在要在app.js里面创建数据传递过去,需要注意一点就是传递的数据必须创建在渲染组件元素的render()函数里面,创建在render()方法之外,是没有效果的,如果是简单组件,就直接声明一个数据数组, 数据声明好之后,直接在组件上传递

function App() {
  const Head = [
    { header: 'Name' },
    {header: 'Job'}
  ]
  return (
    <div className="App">
        // 传递数据
        <Table Head={Head} />
    </div>
  );
}

接下来就可以在Table组件的render函数通过es6方法从props里面拿到数据赋值给新声明的变量,注意必须在render()方法里面声明获取,简单函数直接声明获取获取

// react里面列表渲染时通过map()方法实现的,因为map()方法返回的是一个结果数组
// 需要注意的是每一个循环创建的react元素必须赋予一个key值,这是唯一标识符,同一个react元素里不能相同
const TableHead = (props) => {
  const myHead = props.Head.map((item, index) => {
    return <th key={index}>{item.header}</th>
  })
  return (
    <thead>
      <tr>
        {myHead}
      </tr>
    </thead>
  )
}

class Table extends Component {
  render() {
    // 拿取元素
    const {Head} = this.props
    return (
      <table>
        <TableHead Head={Head} />
        <TableBody />
      </table>
    )
  }
}

扩展一:

将使用单独的Body数组将tbody的值也传到table.js中

import './App.css';
import {
  HashRouter as Router,
  // BrowserRouter as Router,
  Route,
} from 'react-router-dom';
import help from "./page/help";
import home from "./page/home";
import Table from "./page/Table";
import Table1 from "./page/Table1"

function App() {
    const Head = [
        {header: 'Name'},
        {header: 'Job1'}
    ]
    const Body = [
        {
            name: '李狗蛋',
            job: '程序猿',
        },
        {
            name: '王翠花',
            job: '攻城狮',
        },
        {
            name: '二狗子',
            job: '加班狗',
        }
    ]
  return (
      // 显示导航栏并在下方显示选中的页面内容
      <Router>
        <div>
          <Route exact path="/" component={home}/>
          <Route path="/help" component={help}/>
          <Table Head={Head} Body={Body}/>
        </div>
      </Router>
  );
}

export default App;

table.js

import React, {Component} from 'react'

// 方法三<TableHead Head={Head}/>
const TableHead = (props) => {
    console.log('Head',props)
    const myHead = props.Head.map((item,index) => {
        return <th key={index}>{item.header}</th>
    })
    return (
        <thead>
        <tr>{myHead}</tr>
        </thead>
    )
}

const TableBody = (props) => {
    console.log('Body',props)
    const myBody = props.Body.map((item1,index1) => {
        return <tr key={index1}>
            <td>{item1.name}</td>
            <td>{item1.job}</td>
        </tr>
    })
    return (
        <tbody>{myBody}</tbody>
    )
}


class Table extends Component{
    render() { 
        // 拿取传递过来的数据 <Table Head={Head} Body={Body}/>
        // {Head,Body}的名字与table的属性名相同
        const {Head,Body} = this.props
        console.log('total', this.props)
        return (
            <table>
                {/*二. 调用组件,相互嵌套*/}
                <TableHead Head={Head}/>
                <TableBody Body={Body}/>

            </table>
        )
    }
}

export default Table

扩展二:

使用整个数组将Head和Body的值传到Table1.js中

import './App.css';
import {
  HashRouter as Router,
  // BrowserRouter as Router,
  Route,
} from 'react-router-dom';
import help from "./page/help";
import home from "./page/home";
import Table from "./page/Table";
import Table1 from "./page/Table1"

function App() {
    const state = {
        Head: [
            {header: 'Name'},
            {header: 'Job1'}
        ],
        Body: [
            {
                name: '李狗蛋',
                job: '程序猿',
            },
            {
                name: '王翠花',
                job: '攻城狮',
            },
            {
                name: '二狗子',
                job: '加班狗',
            }
        ]
    }
  return (
      // 显示导航栏并在下方显示选中的页面内容
      <Router>
        <div>
          <Route exact path="/" component={home}/>
          <Route path="/help" component={help}/>
          <Table Head={Head} Body={Body}/>
          <Table1 state={state}/>
        </div>
      </Router>
  );
}

export default App;

Table1.js

import React, {Component} from 'react'

const TableHead = (props) => {
    const myHead = props.Head.map((item,index) => {
        return <th key={index}>{item.header}</th>
    })
    return (
        <thead>
        <tr>{myHead}</tr>
        </thead>
    )
}

const TableBody = (props) => {
    const myBody = props.Body.map((item,index) => {
        return <tr key={index}>
            <td>{item.name}</td>
            <td>{item.job}</td>
        </tr>
    })
    return (
        <tbody>{myBody}</tbody>
    )
}
class Table1 extends Component{
    render() {
        // 获取父组件定义的变量
        const {state} = this.props
        console.log('state', {state})
        return (
            <table>
                <TableHead Head={state.Head}/>
                <TableBody Body={state.Body}/>
            </table>
        )
    }
}
export default Table1

运行结果:(扩展一和扩展二运行结果相同)

ios react 包 打debug react打包流程_javascript

七:子组件向父组件传值

父组件:

import React from 'react';
import Child from "./Child";

export default  class home extends React.Component{
    getData=(data)=>{
        console.log(data)
        document.getElementById("changeData").textContent = data
    }
    render(){
        return <div>
            <p>
                父组件<br/>
                点击子组件,向父组件传值
                {/*将传过来的值显示在id='changeData'的控件里*/}
                <div id='changeData'></div>
                <Child getData={this.getData}/>
            </p>
        </div>
    }
}

子组件:Child.js

import React, {Component} from 'react'
export default class Child extends Component{
    state = {
        data:[1,2,3]
    }
    render() {
        const {data} = this.state
        return (
            <div>
                <button onClick={()=> {this.props.getData(data)}}>子组件</button>
            </div>
        )
    }
}

八. 父组件向子组件传值,子组件操作修改父组件

在表格的每一行增加删除按钮, Table.js和Table1.js分别是两种方法传值,删除方法也不同

Table.js

(Table.js的方法不可取,如果不设置state数据的话,删除数据,后台打印信息中可删除,但页面不会变化。在此仅做对比参考)

import React, {Component} from 'react'

// 方法三<TableHead Head={Head}/>
const TableHead = (props) => {
    console.log('Head',props)
    const myHead = props.Head.map((item,index) => {
        return <th key={index}>{item.header}</th>
    })
    return (
        <thead>
        <tr>{myHead}</tr>
        </thead>
    )
}

const TableBody = (props) => {
    console.log('Body',props)
    const myBody = props.Body.map((item1,index1) => {
        return <tr key={index1}>
            <td>{item1.name}</td>
            <td>{item1.job}</td>
            <td>
                <button onClick={()=>props.removeTr(props.Body,index1)}>Delete</button>
            </td>
        </tr>
    })
    return (
        <tbody>{myBody}</tbody>
    )
}


class Table extends Component{
    render() {
        // 拿取传递过来的数据
        const {Head,Body, removeTr} = this.props
        console.log('total', this.props)
        return (
            <table>
                {/*二. 调用组件,相互嵌套*/}
                <TableHead Head={Head}/>
                <TableBody Body={Body} removeTr={removeTr}/>

            </table>
        )
    }
}

export default Table

Table1.js

import React, {Component} from 'react'

const TableHead = (props) => {
    const myHead = props.Head.map((item,index) => {
        return <th key={index}>{item.header}</th>
    })
    return (
        <thead>
        <tr>{myHead}</tr>
        </thead>
    )
}

const TableBody = (props) => {
    console.log('body1', props)
    const myBody = props.Body.map((item,index) => {
        return <tr key={index}>
            <td>{item.name}</td>
            <td>{item.job}</td>
            <td>
                <button onClick={()=>props.removeTr1(index)}>Delete</button>
            </td>
        </tr>
    })
    return (
        <tbody>{myBody}</tbody>
    )
}
class Table1 extends Component{
    render() {
        const {state,removeTr1} = this.props
        console.log('state', {state})
        return (
            <table>
                <TableHead Head={state.Head}/>
                <TableBody Body={state.Body} removeTr1={removeTr1}/>
            </table>
        )
    }
}
export default Table1

home.js当将this.state放在constructor里时,点击删除按钮,页面中可实际删除。(编译时也不会弹警告)或者将state放在Render外,

1。放在constructor里

import React from 'react';
import {Link} from "react-router-dom";
import Table from "./Table";
import Table1 from "./Table1";

export default  class home extends React.Component{
    constructor(props) {
        super(props);
        this.state = {
            Head: [
                {header: 'Name'},
                {header: 'Job1'}
            ],
            Body: [
                {
                    name: '李狗蛋',
                    job: '程序猿',
                },
                {
                    name: '王翠花',
                    job: '攻城狮',
                },
                {
                    name: '二狗子',
                    job: '加班狗',
                }
            ]
        }
    }
   
    removeTr1 = (index)=> {
        const {Body} = this.state
        this.setState({
            Body: Body.filter((item,ind) => {
                    console.log('index', index+","+ind)
                    console.log('removeTr1', Body.filter((item,index1)=>index1 !== index))
                    return ind !== index
                }
            )
            // Body: Body.filter((item,ind) => ind !== index)
        })
    }
    render(){

        return <div>
            <h2>这是首页内容......</h2>
            <p>
                <div style={{border: '1px solid #fff000',padding: '10px'}}>
                    state 方式传值
                    <Table1 state={this.state} removeTr1={this.removeTr1}/>
                </div>
            </p>
        </div>
    }
}

2。放在render外面

import React from 'react';
import {Link} from "react-router-dom";
import Table1 from "./Table1";

export default  class home extends React.Component{
    removeTr1 = (index)=> {
        const {Body} = this.state
        this.setState({
            Body: Body.filter((item,ind) => {
                    console.log('index', index+","+ind)
                    console.log('removeTr1', Body.filter((item,index1)=>index1 !== index))
                    return ind !== index
                }
            )
            // Body: Body.filter((item,ind) => ind !== index)
        })
    }
    state = {
        Head: [
            {header: 'Name'},
            {header: 'Job1'}
        ],
        Body: [
            {
                name: '李狗蛋',
                job: '程序猿',
            },
            {
                name: '王翠花',
                job: '攻城狮',
            },
            {
                name: '二狗子',
                job: '加班狗',
            }
        ]
    }
    render(){

        return <div>
            <h2>这是首页内容......</h2>
            <p>
                <div style={{border: '1px solid #fff000',padding: '10px'}}>
                    state 方式传值
                    <Table1 state={this.state} removeTr1={this.removeTr1}/>
                </div>
            </p>
        </div>
    }
}

九. Form表单,增加数据

import React, { Component } from 'react'

export default class Form extends Component{
    constructor(props) {
        super(props);
        //初始化input的value值
        this.initValue= {
            name: '',
            job: ''
        }
        // 将初始化的值赋值给state
        this.state = this.initValue
    }
    //input的标签内容改变时执行
    handleChange = (e) => {
        this.setState({
            [e.target.name]: e.target.value,
        })
    }

    //点击提交按钮时
    submitForm = () => {
        //这个方法是父组件那边传过来的,需要把用户输入的数据传过去
        this.props.handleSubmit(this.state)
        console.log('Form submitForm', this.state)
        console.log('Form submitForm', this.props)
        //重置input的value值
        this.setState(this.initValue)
        //在页面显示新增的数据
        document.getElementById("addInput").textContent=JSON.stringify(this.state)
    }

    render() {
        const {name,job} = this.state
        return (
            <form>
              <label>
                  Name:
              </label>
              <input type="text" value={name} name="name" onChange={this.handleChange}/><br/>
              <label>
                  Job:
              </label>
              <input type="text" value={job} name="job" onChange={this.handleChange}/>
              <div id="addInput"></div>
              <input type="button" value="新增" onClick={this.submitForm}/>
            </form>
        );
    }
}

父组件home.js

handleSubmit = (valObj) => {
        // 通过解构的方式,把传过来的数据添加到Body数组里,
        console.log('home handleSubmit', valObj)
        console.log('home handleSubmit', this.state.Body)
        this.setState({
            // Body: this.state.Body.push(valObj)
            Body: [...this.state.Body, valObj]
        })
        console.log('home handleSubmit2', this.state.Body)
    }

十. 完整代码:

将原来放在App.js中的代码放在了home.js中,完成了父子组件的传值和调用

学习要点:

1. Table1.js:父组件向子组件传值,显示列表数据,删除数据并刷新页面;组件的嵌套;

2. Form.js: 提交表单,增加数据,向父组件传值并刷新页面;

3. Child.js: 子组件向父组件传值

4. Button.js: 生命周期的调用

5. App.js: 展示了两种路由

 

home.js

import React from 'react';
import {Link} from "react-router-dom";
import Child from "./Child";
import Table from "./Table";
import Table1 from "./Table1";
import Button from "./Button";
import Form from "./Form";

export default  class home extends React.Component{
    getData=(data)=>{
        console.log(data)
        document.getElementById("changeData").textContent = data
    }
    removeTr = (Body, index)=> {
        // const {Body} = this.Body
        this.setState({
            Body: Body.filter((item,ind) => {
                    console.log('index', index+","+ind)
                    console.log('dfsdf', Body.filter((item,index1)=>index1 !== index))
                    return ind !== index
                }
            )
            // Body: Body.filter((item,ind) => ind !== index)
        })
    }
    removeTr1 = (index)=> {
        const {Body} = this.state
        this.setState({
            Body: Body.filter((item,ind) => {
                    console.log('index', index+","+ind)
                    console.log('removeTr1', Body.filter((item,index1)=>index1 !== index))
                    return ind !== index
                }
            )
            // Body: Body.filter((item,ind) => ind !== index)
        })
    }
    handleSubmit = (valObj) => {
        // 通过解构的方式,把传过来的数据添加到Body数组里,
        console.log('home handleSubmit', valObj)
        console.log('home handleSubmit', this.state.Body)
        this.setState({
            // Body: this.state.Body.push(valObj)
            Body: [...this.state.Body, valObj]
        })
        console.log('home handleSubmit2', this.state.Body)
    }
    state = {
        Head: [
            {header: 'Name'},
            {header: 'Job1'}
        ],
        Body: [
            {
                name: '李狗蛋',
                job: '程序猿',
            },
            {
                name: '王翠花',
                job: '攻城狮',
            },
            {
                name: '二狗子',
                job: '加班狗',
            }
        ]
    }
    render(){
        const Head = [
            {header: 'Name'},
            {header: 'Job1'}
        ]
        const Body = [
            {
                name: '李狗蛋',
                job: '程序猿',
            },
            {
                name: '王翠花',
                job: '攻城狮',
            },
            {
                name: '二狗子',
                job: '加班狗',
            }
        ]

        return <div>
            <h2>这是首页内容......</h2>
            <p>
                <div style={{border: '1px solid #fff000',padding: '10px'}}>
                    各自传值
                    <Table Head={Head} Body={Body} removeTr={this.removeTr}/>
                </div>
                {/*<Table Head={Head} Body={Body}/>*/}
                <div style={{border: '1px solid #fff000',padding: '10px'}}>
                    state 方式传值
                    <Table1 state={this.state} removeTr1={this.removeTr1}/>
                </div>
            </p>
            <p><Link to="/lifecycle">React生命周期</Link></p>
            <p><Button/></p>
            <p><Link to="/help/">帮助</Link></p>
            <p>
                父组件<br/>
                点击子组件,向父组件传值
                <div id='changeData'></div>
                <Child getData={this.getData}/>
            </p>
            <p>
                <Form handleSubmit={this.handleSubmit}/>
            </p>
        </div>
    }
}

Table1.js : 父组件向子组件传值,显示表格信息,删除数据

import React, {Component} from 'react'

const TableHead = (props) => {
    const myHead = props.Head.map((item,index) => {
        return <th key={index}>{item.header}</th>
    })
    return (
        <thead>
        <tr>{myHead}</tr>
        </thead>
    )
}

const TableBody = (props) => {
    console.log('Table1 body1', props)
    const myBody = props.Body.map((item,index) => {
        return <tr key={index}>
            <td>{item.name}</td>
            <td>{item.job}</td>
            <td>
                <button onClick={()=>props.removeTr1(index)}>Delete</button>
            </td>
        </tr>
    })
    return (
        <tbody>{myBody}</tbody>
    )
}
class Table1 extends Component{
    render() {
        const {state,removeTr1} = this.props
        console.log('Table1 state', {state})
        return (
            <table>
                <TableHead Head={state.Head}/>
                <TableBody Body={state.Body} removeTr1={removeTr1}/>
            </table>
        )
    }
}
export default Table1

Form.js: 增加数据,向父组件传值

import React, { Component } from 'react'

export default class Form extends Component{
    constructor(props) {
        super(props);
        //初始化input的value值
        this.initValue= {
            name: '',
            job: ''
        }
        // 将初始化的值赋值给state
        this.state = this.initValue
    }
    //input的标签内容改变时执行
    handleChange = (e) => {
        this.setState({
            [e.target.name]: e.target.value,
        })
    }

    //点击提交按钮时
    submitForm = () => {
        //这个方法是父组件那边传过来的,需要把用户输入的数据传过去
        this.props.handleSubmit(this.state)
        console.log('Form submitForm', this.state)
        console.log('Form submitForm', this.props)
        //重置input的value值
        this.setState(this.initValue)
        //在页面显示新增的数据
        document.getElementById("addInput").textContent=JSON.stringify(this.state)
    }

    render() {
        const {name,job} = this.state
        return (
            <form>
              <label>
                  Name:
              </label>
              <input type="text" value={name} name="name" onChange={this.handleChange}/><br/>
              <label>
                  Job:
              </label>
              <input type="text" value={job} name="job" onChange={this.handleChange}/>
              <div id="addInput"></div>
              <input type="button" value="新增" onClick={this.submitForm}/>
            </form>
        );
    }
}

Child.js:子组件向父组件传值

import React, {Component} from 'react'
export default class Child extends Component{
    state = {
        data:[1,2,3]
    }
    render() {
        const {data} = this.state
        return (
            <div>
                <button onClick={()=> {this.props.getData(data)}}>子组件</button>
            </div>
        )
    }
}

App.js:

import './App.css';
import {
  // Switch,
  HashRouter as Router,
  // BrowserRouter as Router,
  Route,
} from 'react-router-dom';
import help from "./page/help";
import home from "./page/home";
import Button from "./page/Button"

function App() {
  return (
      // <Router>
      //   {/*只显示某一页的内容 http://localhost:3000/#/或http://localhost:3000/#/help*/}
      //   <Switch>
      //     <Route path="/" exact component={home} />
      //     <Route path="/help" component={help}/>
      //   </Switch>
      // </Router>
      // 显示导航栏并在下方显示选中的页面内容
      <Router>
        <div>
          <Route exact path="/" component={home}/>
          <Route path="/help" component={help}/>
          <Route path="/lifecycle" component={Button}/>
          {/*<Table Head={Head} Body={Body}/>*/}
        </div>
      </Router>

  );
}

export default App;

补充:Button.js生命周期的调用:

import React, {Component} from 'react'

export default class Button extends Component{
    constructor(props) {
        super(props);
        this.state = {data: 0};
        this.setNewNumber = this.setNewNumber.bind(this);
    }

    setNewNumber() {
        this.setState({data: this.state.data +1})
    }

    render() {
        return (
            <div style={{border: '1px solid #fff000',padding: '10px'}}>
                <button onClick={this.setNewNumber}>INCREMENT</button>
                <Content myNumber={this.state.data}></Content>
            </div>
        )
    }
}

class Content extends Component{
    // 在渲染前调用,在客户端也在服务端。
    componentWillMount() {
        console.log('Component Will mount')
    }
    // 在第一次渲染后调用,只在客户端。之后组件已经生成了对应的DOM结构,可以通过this.getDOMNode()来进行访问。 如果你想和其他JavaScript框架一起使用,可以在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操作(防止异步操作阻塞UI)。
    componentDidMount() {
        console.log('Component Did mount')
    }

    // 在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用。
    componentWillReceiveProps(nextProps, nextContext) {
        console.log('Component Will Receive props', nextProps)
    }
    // 返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用
    shouldComponentUpdate(nextProps, nextState, nextContext) {
        console.log('shouldComponentUpdate', nextProps)
        console.log('shouldComponentUpdate', nextState)
        return true;
    }

    // 在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用
    componentWillUpdate(nextProps, nextState, nextContext) {
        console.log('component Will update', nextProps)
        console.log('component Will update', nextState)
    }

    // 在组件完成更新后立即调用。在初始化时不会被调用。
    componentDidUpdate(prevProps, prevState, snapshot) {
        console.log('component Did update', prevProps)
        console.log('component Did update', prevState)
    }

    // 在组件从 DOM 中移除之前立刻被调用。
    componentWillUnmount() {
        console.log('component Will unmount')
    }

    render() {
        return (
            <div>
                <h3>{this.props.myNumber}</h3>
            </div>
        )
    }

}