17、React基础、react之约束|受控组件、setState、生命周期、组件写法、插槽,portal、React.Children、Model多层弹窗组件、react.15.6.0.js源码外框、ant-design-pro构成、前端路由及触发条件

一、react基础
1、真实DOM和虚拟DOM
(1)真实DOM,用户每次操作DOM(文档对象模型),都会引起BOM(浏览器对象模型)重新渲染
(2)虚拟DOM,用户每次操作DOM(文档对象模型),都会改变虚拟DOM(堆内存的一个对象),最后一次性地渲染到BOM上。
2、React的缺点和优点  
(1)缺点:
(A)React本身只是一个V,不是一个完整的框架,不是一套完整的框架
(B)需要加上React-Router和React-Redux才能成为一套完整的框架  
(2)优点:
(A)单向数据流动;
(B)虚拟DOM取代物理DOM作为操作对象;
(C)用JSX语法取代HTML模板,在JavaScript里声明式地描述UI。  
3、React组件3个部分
(1)React组件基本上由3个部分组成——属性(props)、状态(state)以及生命周期方法
(2)React组件一旦接收到的参数(即props)或自身状态有所改变,React组件就会执行相应的生命周期方法,最后渲染。
(3)整个过程完全符合传统组件所定义的组件职责(“属性更新”与“状态改变”)。
(4)以上内容来自《深入React技术栈》第18和30页。
4、ref可以设置回调函数
(1)<input type="text" ref="myInput"/>
this.refs.myInput.value ="22"; //this.$refs.myInput.value ="22"  减少获取dom节点的消耗
(2)ref属性可以设置为一个回调函数,这也是官方强烈推荐的用法;这个函数执行的时机为:
(3)组件被挂载后,回调函数被立即执行,回调函数的参数为该组件的具体实例。
(4)组件被卸载或者原有的ref属性本身发生变化时,回调也会被立即执行,此时回调函数参数为null,以确保内存泄露。
5、为什么不能用index做key? 
(1)react会根据key来决定是否重新构建该组件
(2)删除和添加操作,会使一个组件使用另一个的组件的index,进而key,进而data
6、状态提声(父组件的函数作为属性传给子组件)
(1)在父组件的constructor中定义状态
(2)在父组件的方法中执行this.setState({})
(3)把父组件的方法作为属性fromParent传给子组件
(4)在子组件的方法中加上this.props.fromParent(e.target.value);
(5)触发子组件的事件,执行子组件的方法,改变父组件的状态
8、跨多级组件传参原理
//祖父组件声明自己支持 context
static childContextTypes = {
  color:PropTypes.string,
  callback:PropTypes.func,
}
//祖父组件提供一个函数,用来返回相应的 context 对象
getChildContext(){
  return{
    color:"red",
    callback:this.callback.bind(this)
  }
}
//孙子组件声明自己需要使用 context
static contextTypes = {
  color:PropTypes.string,
  callback:PropTypes.func,
}

二、约束性组件和非约束性组件(受控组件和非受控组件)
1、约束性组件
<input type="text" value={this.state.name} onChange={this.handleChange} />
handleChange: function(e) {
  this.setState({name: e.target.value});
}
//用户输入内容A>触发onChange事件>handleChange中设置state.name="A"渲染input使他的value变成A
2、非约束性组件
<input type="text" defaultValue="a" />//用户输入A -> input 中显示A 
3、React 把 input,textarea 和 select 三个组件做了抽象和封装,他们有统一的 value 属性 和 onChange 事件。
<input type='text' name='intro'  value={this.state.email} onChange={this.handleEmail} />
<textarea type='text' name='intro'  value={this.state.intro} onChange={this.handleIntro} />
<textarea type='text' name='intro'  value={this.state.intro} onChange={this.handleIntro} />
4、checkbox改变的不是 value ,而是 checked 状态。
<input type='radio' name='gender' checked={this.state.male==='MALE'} onChange={this.handleGender} value='MALE' />
<input type='radio' name='gender' checked={this.state.male==='FEMALE'} onChange={this.handleGender} value='FEMALE' />
handleGender(e){
  this.setState({
    male:e.target.value
  })
}

三、setState
1、this.setState接收两种参数
(1)对象+函数(可选):传入的对象浅层合并到新的state中
(2)函数+函数(可选):第一个函数接受两个参数,第一个是当前state,第二个是当前props,该函数返回一个对象,和直接传递对象参数是一样的,就是要修改的state;第二个函数参数是state改变后触发的回调。
2、this.setState何时同步何时异步?
(1)异步,由react控制的事件处理程序
(2)同步,react控制之外的事件中调用setState是同步更新的。比如原生js绑定的事件,setTimeout/setInterval等。
(3)大部分开发中用到的都是react封装的事件,比如onChange、onClick、onTouchMove等,这些事件处理程序中的setState都是异步处理的。
3、this.setState何时渲染
(1)死循环:this.setState执行时,会根据_compositeLifeCycleState是否为null,来决定是否重新渲染,因此在有的生命周期里,会产生死循环。
(2)只生效一次:this.setState最后执行队列时,先用变量获取并存储state,后来直接修改变量,最后把变量赋值给state,页面渲染。
handleClick() {
  //const count = this.state.count 下面 this.setState 多次执行,但只生效一次。因为似乎存在此行代码。
  this.setState({
    count: count + 1
  })
  this.setState({
    count: count + 1
  })
}

四、React生命周期
1、React15、React16完整生命周期比较
A、实例化
(1)React15之ES5写法:propTypes = {}; getDefaultProps(){return{}};
  //React16之ES6写法:static propTypes = {}; static defaultProps = {}; 
(2)React15之ES5写法:getInitialState(){return{}};
  //React16之ES6写法:constructor
(3)React15之ES5写法:componentWillMount//执行setState会合并到初始化状态中;获取从属性生成的状态;此后生命状态会被重置为null;
  //React16之ES6写法:static getDerivedStateFromProps//执行setState会合并到初始化状态中;获取从属性生成的状态
(4)render//执行setState会发起updateComponent导致-死循环
(5)componentDidMount//执行setState会导致更新;这是发起异步请求去API获取数据的绝佳时期
B、存在期
(1)React15之ES5写法:componentWillReceiveProps//执行setState会合并到状态中;此后生命状态会被重置为null
  //React16之ES6写法:static getDerivedStateFromProps//执行setState会合并到状态中;
(2)shouldComponentUpdate//执行setState会发起updateComponent导致-死循环
(3)React15之ES5写法:componentWillUpdate//执行setState会发起updateComponent导致-死循环
  //React16之ES6写法:此处没有componentWillUpdate
(4)render//执行setState会发起updateComponent导致-死循环
  //React16之ES6写法:此处新增getSnapshotBeforeUpdate//执行setState会发起updateComponent导致-死循环
(5)componentDidUpdate//可以有条件地执行setState
C、销毁期
(1)componentWillUnmount//等待页面卸载,改变state没意义。
2、React16生命周期(过渡)
(1)沿用了3个componentWillMount,componentWillReceiveProps,componentWillUpdate
(2)新增了2个getDerivedStateFromProps,getSnapshotBeforeUpdate
(3)在实际项目中,沿用方案和新增方案只能二选一,不能混用
3、React17生命周期(全新)
(1)弃用了3个componentWillMount,componentWillReceiveProps,componentWillUpdate
(2)启用了2个getDerivedStateFromProps,getSnapshotBeforeUpdate
(3)新增了1个componentDidCatch(处理错误)
来源:https://blog.csdn.net/liuqiao0327/article/details/107297106

五、React组件写法
1、React15.6.1版组件之ES5写法
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React实例</title>
<script src="https://lib.baomitu.com/react/15.6.1/react.js"></script>
<script src="https://lib.baomitu.com/react/15.6.1/react-dom.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body>
<div ></div>
<script type="text/babel">
var Button = React.createClass({
  setNewNumber(number,event) {
    this.setState({number: this.state.number + 1})
  },
  getDefaultProps() {
    return { name: "计数器" };
  },
  getInitialState() {
    return{number: 0};
  },
  render() {
    return (
      <div>
        <button onClick = {this.setNewNumber.bind(null,this.state.number,event)}>点击{this.props.name}</button>
        <Text myNumber = {this.state.number}></Text>
      </div>
    );
  }
})
var Text = React.createClass({
  //一、以下实例化时期
  getDefaultProps() {
    console.log("1.getDefaultProps 获取默认属性");
    return { };
  },
  getInitialState() {
    console.log("2.getInitialState 获取初始状态");
    return { };
  },
  componentWillMount() {
    console.log("3.componentWillMount 此组件将要被渲染到目标组件内部");
  },
  componentDidMount() {
    console.log("5.componentWillMount 此组件已经被渲染到目标组件内部");
  },
  //二、以下存在时期
  componentWillReceiveProps() {
    console.log("6.componentWillReceiveProps 此组件将要收到属性");
  },
  shouldComponentUpdate(newProps, newState) {
    console.log("7.shouldComponentUpdate 组件是否应该被更新");
    return true;
  },
  componentWillUpdate() {
    console.log("8.componentWillUpdate 组件将要被更新");
  },
  componentDidUpdate() {
    console.log("10.componentDidUpdate 组件已经更新完成");
  },
  //三、以下销毁时期
  componentWillUnmount() {
    console.log("11.componentWillUnmount 组件将要销毁");
  },
  render() {
    console.log("4和9.render 组件将要渲染");
    return (
      <div>
        <h3>{this.props.myNumber}</h3>
      </div>
    );
  }
})
ReactDOM.render(
   <div>
      <Button />
   </div>,
  document.getElementById('example')
);
</script>
</body>
</html>
2、React16.4.0版组件之ES6写法
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React实例</title>
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body>
<div ></div>
<script type="text/babel">
class Button extends React.Component {
  //name="计算器";state = {number: 0};
  //上下写法,二选一
  constructor(props) {
    super(props);
    this.name="计算器";
    this.state = {number: 0};
  };
  setNewNumber(number,event) {
    this.setState({number: this.state.number + 1})
  };
  render() {
    return (
      <div>
        <button onClick = {this.setNewNumber.bind(this,this.state.number,event)}>点击{this.name}</button>
        <Text myNumber = {this.state.number}></Text>
      </div>
    );
  }
}
class Text extends React.Component {
  //一、以下实例化时期
  constructor(props) {
    super(props);
    console.log("2.constructor 获取初始状态");
  }
  componentWillMount() {
    console.log("3.componentWillMount 此组件将要被渲染到目标组件内部");
  }
  componentDidMount() {
    console.log("5.componentWillMount 此组件已经被渲染到目标组件内部");
  }
  //二、以下存在时期
  componentWillReceiveProps() {
    console.log("6.componentWillReceiveProps 此组件将要收到属性");
  }
  shouldComponentUpdate(newProps, newState) {
    console.log("7.shouldComponentUpdate 组件是否应该被更新");
    return true;
  }
  componentWillUpdate() {
    console.log("8.componentWillUpdate 组件将要被更新");
  }
  componentDidUpdate() {
    console.log("10.componentDidUpdate 组件已经更新完成");
  }
  //三、以下销毁时期
  componentWillUnmount() {
    console.log("11.componentWillUnmount 组件将要销毁");
  }
  render() {
    console.log("4和9.render 组件将要渲染");
    return (
      <div>
        <h3>{this.props.myNumber}</h3>
      </div>
    );
  }
}
ReactDOM.render(
   <div>
      <Button />
   </div>,
  document.getElementById('example')
);
</script>
</body>
</html>
来源 https://www.runoob.com/try/try.php?filename=try_react_life_cycle2
 
六、插槽
1、portal插槽
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React插槽实例</title>
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body>
  <div ></div>
  <div ></div>
</body>
<script type="text/babel">
const container = document.getElementById('container');
const outer = document.getElementById('outer');
class Model extends React.Component {
  constructor(props) {
    super(props);
    this.div = document.createElement('div');
  }
  componentDidMount() {
    outer.appendChild(this.div);
  }
  componentWillUnmount() {
    outer.removeChild(this.div);
  }
  render() {
    return ReactDOM.createPortal(
      this.props.children,
      this.div
    );
  }
}
class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {clicks: 0};
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick() {
    this.setState(state => ({
      clicks: state.clicks + 1
    }));
  }
  render() {
    return (
      <div onClick={this.handleClick}>
        <div>{this.state.clicks}</div>
        <div><button>Click</button></div>
        <Model>
          <div>
            <button className="Model">Click</button>
          </div>
        </Model>
      </div>
    );
  }
}
ReactDOM.render(<Parent/>, container);
</script>
2、React.Children插槽
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React插槽实例</title>
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body>
  <div ></div>
  <div ></div>
</body>
<script type="text/babel">
class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {clicks: 0};
    this.handleClick = this.handleClick.bind(this);
  }
  handleClick(event) {
    console.log(event)
    this.setState(state => ({
      clicks: state.clicks + 1
    }));
  }
  render() {
    var that = this;
    return (
      <div>
        <div>{this.state.clicks}</div>
        <div><button onClick={this.handleClick}>clicks</button></div>
        <ul>
          {
            React.Children.map(this.props.children,function(item,index){
              if(index !=1){
                return <li onClick={that.handleClick}>{item}</li>
              }else{
                return <li onClick={that.handleClick}>{item}---{index+1}</li>
              }
            })
          }
        </ul>
      </div>
    );
  }
}
ReactDOM.render(<Parent>
  <span pointer',userSelect: 'none'}}>插槽一</span>
  <span pointer',userSelect: 'none'}}>插槽二</span>
  <span pointer',userSelect: 'none'}}>插槽三</span>
</Parent>, document.getElementById('container'));
</script>
</html>

七、Model多层弹窗
1、不可拖拽(含插槽)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React弹窗实例</title>
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<style>
  .simpleDialog {
    position: fixed;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    display: none;
    justify-content: center;
    align-items: center;
  }
  .simpleDialog .mask {
    position: fixed;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    background: black;
    opacity: 0.5;
  }
  .simpleDialog .content {
    position: fixed;
    background: white;
    opacity: 1;
    display: flex;
    flex-direction: column;
  }
  .simpleDialog .content .title {
    display: flex;
    background: blue;
    color: white;
    padding: 10px;
    cursor: pointer;
  }
  .simpleDialog .content .title {
    display: flex;
    background: blue;
    color: white;
    padding: 10px;
    cursor: pointer;
  }
  .simpleDialog .content .conform {
    display: flex;
    justify-content: center;
    padding: 10px;
    background: blue;
  }
</style>
</head>
<body>
  <div ></div>
</body>
</html>
<script type="text/babel">
const container = document.getElementById('container');
class Model extends React.Component {
  constructor(props) {
    super(props);
  }
  componentDidUpdate(){
    var id = this.props.id||'simpleDialog';
    if(this.props.isShow.isShow){
      document.getElementById(id).style.display = 'flex';
    }else{
      document.getElementById(id).style.display = 'none';
    }
  }
  close() {
    if(this.props.close){
      this.props.close()
    }
  }
  open() {
    if(this.props.open){
      this.props.open()
    }
  }
  render() {
    return (
      <div>
        <div className="simpleDialog" |'simpleDialog'}>
          <div className="mask"></div>
          <div className="content">
            <div className="title">
              <span>系统消息</span>
            </div>
            <div |'800px',height:this.props.height||'600px'}}>
              {
                React.Children.map(this.props.children,function(item,index){
                  return item
                })
              }
            </div>
            <div className="conform">
              <button onClick={this.close.bind(this)}>关闭</button>
              <button onClick={this.open.bind(this)}>打开</button>
            </div>
          </div>
        </div>
      </div>
    );
  }
}
class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      outShow: {isShow: false},
      midShow: {isShow: false},
      inShow: {isShow: false},
    };
  }
  outOpen() {
    this.setState({
      outShow: {isShow: true}
    });
  }
  outClose() {
    this.setState({
      outShow: {isShow: false}
    });
  }
  midOpen() {
    this.setState({
      midShow: {isShow: true}
    });
  }
  midClose() {
    this.setState({
      midShow: {isShow: false}
    });
  }
  inOpen() {
    this.setState({
      inShow: {isShow: true},
    });
  }
  inClose() {
    this.setState({
      inShow: {isShow: false},
    });
  }
  render() {
    return (
      <div>
        <div><button onClick={this.outOpen.bind(this)}>出现弹窗</button></div>
        <Model isShow={this.state.outShow} open={this.midOpen.bind(this)} close={this.outClose.bind(this)}  width="900px" height="600px">
          这是插槽1
          <Model isShow={this.state.midShow} open={this.inOpen.bind(this)} close={this.midClose.bind(this)}  width="600px" height="400px">
            这是插槽2
            <Model isShow={this.state.inShow} close={this.inClose.bind(this)}  width="300px" height="200px">
              这是插槽3
            </Model>
          </Model>
        </Model>
      </div>
    );
  }
}
ReactDOM.render(<Parent/>, container);
</script>
2、可拖拽(含插槽)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>React弹窗实例</title>
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<script>
  function drag(wholeTitleId, wholeContentId) {
    var wholeTitleId = wholeTitleId||'titleId';
    var wholeContentId = wholeContentId||'contentId';
    var oDiv = document.getElementById(wholeContentId);
    if(!oDiv) return;
    oDiv.onmousedown = down;
    function processThis(fn, nowThis) {
      return function (event) {
        fn.call(nowThis, event);
      };
    }
    function down(event) {
      event = event || window.event;
      if (event.target.id != wholeTitleId) return;
      this.initOffsetLeft = this.offsetLeft;
      this.initOffsetTop = this.offsetTop;
      this.initClientX = event.clientX;
      this.initClientY = event.clientY;
      this.maxOffsetWidth =
        (document.documentElement.clientWidth || document.body.clientWidth) -
        this.offsetWidth;
      this.maxOffsetHeight =
        (document.documentElement.clientHeight ||
          document.body.clientHeight) - this.offsetHeight;
      if (this.setCapture) {
        this.setCapture();
        this.onmousemove = processThis(move, this);
        this.onmouseup = processThis(up, this);
      } else {
        document.onmousemove = processThis(move, this);
        document.onmouseup = processThis(up, this);
      }
    }
    function move(event) {
      var nowLeft = this.initOffsetLeft + (event.clientX - this.initClientX);
      var nowTop = this.initOffsetTop + (event.clientY - this.initClientY);
      this.style.left = nowLeft + 'px';
      this.style.top = nowTop + 'px';
    }
    function up() {
      if (this.releaseCapture) {
        this.releaseCapture();
        this.onmousemove = null;
        this.onmouseup = null;
      } else {
        document.onmousemove = null;
        document.onmouseup = null;
      }
    }
  }; 
</script>
<style>
  .simpleDialog {
    position: fixed;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    display: none;
    justify-content: center;
    align-items: center;
  }
  .simpleDialog .mask {
    position: fixed;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    background: black;
    opacity: 0.5;
  }
  .simpleDialog .content {
    position: fixed;
    background: white;
    opacity: 1;
    display: flex;
    flex-direction: column;
  }
  .simpleDialog .content .title {
    display: flex;
    background: blue;
    color: white;
    padding: 10px;
    cursor: pointer;
  }
  .simpleDialog .content .title {
    display: flex;
    background: blue;
    color: white;
    padding: 10px;
    cursor: pointer;
  }
  .simpleDialog .content .conform {
    display: flex;
    justify-content: center;
    padding: 10px;
    background: blue;
  }
</style>
</head>
<body>
  <div ></div>
</body>
</html>
<script type="text/babel">
const container = document.getElementById('container');
class Model extends React.Component {
  constructor(props) {
    super(props);
  }
  componentDidUpdate(){
    var id = this.props.id||'simpleDialog';
    var title = this.props.title||'title';
    var content = this.props.content||'content';
    if(this.props.isShow.isShow){
      document.getElementById(id).style.display = 'flex';
      drag(title,content)
    }else{
      document.getElementById(id).style.display = 'none';
    }
  }
  close() {
    if(this.props.close){
      this.props.close();
      var content = this.props.content;
      document.getElementById(content).style.cssText = "position:fixed;";
    }
  }
  open() {
    if(this.props.open){
      this.props.open()
    }
  }
  render() {
    return (
      <div>
        <div className="simpleDialog" |'simpleDialog'}>
          <div className="mask"></div>
          <div className="content" |'content'}>
            <div className="title" |'title'}>
              <span>系统消息</span>
            </div>
            <div |'800px',height:this.props.height||'400px'}}>
              {
                React.Children.map(this.props.children,function(item,index){
                  return item
                })
              }
            </div>
            <div className="conform">
              <button onClick={this.close.bind(this)}>关闭</button>
              <button onClick={this.open.bind(this)}>打开</button>
            </div>
          </div>
        </div>
      </div>
    );
  }
}
class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      outShow: {isShow: false},
      midShow: {isShow: false},
      inShow: {isShow: false},
    };
  }
  outOpen() {
    this.setState({
      outShow: {isShow: true}
    });
  }
  outClose() {
    this.setState({
      outShow: {isShow: false}
    });
  }
  midOpen() {
    this.setState({
      midShow: {isShow: true}
    });
  }
  midClose() {
    this.setState({
      midShow: {isShow: false}
    });
  }
  inOpen() {
    this.setState({
      inShow: {isShow: true},
    });
  }
  inClose() {
    this.setState({
      inShow: {isShow: false},
    });
  }
  render() {
    return (
      <div>
        <div><button onClick={this.outOpen.bind(this)}>出现弹窗</button></div>
        <Model isShow={this.state.outShow} open={this.midOpen.bind(this)} close={this.outClose.bind(this)}  title="title1" content="content1" width="900px" height="600px">
          这是插槽1
          <Model isShow={this.state.midShow} open={this.inOpen.bind(this)} close={this.midClose.bind(this)}  title="title2" content="content2" width="600px" height="400px">
            这是插槽2
            <Model isShow={this.state.inShow} close={this.inClose.bind(this)}  title="title3" content="content3" width="300px" height="200px">
              这是插槽3
            </Model>
          </Model>
        </Model>
      </div>
    );
  }
}
ReactDOM.render(<Parent/>, container);
</script>

八、React.15.6.0源码外框
/**
 * React v15.6.0
 */
(function (allFn) {
  if (typeof exports === "object" && typeof module !== "undefined") {
    module.exports = allFn()
  } else if (typeof define === "function" && define.amd) {
    define([], allFn)
  } else {
    var tempGlobal;
    if (typeof window !== "undefined") {
      tempGlobal = window
    } else if (typeof global !== "undefined") {
      tempGlobal = global
    } else if (typeof self !== "undefined") {
      tempGlobal = self
    } else {
      tempGlobal = this
    }
    tempGlobal.React = allFn()
  }
})(function () {
  var define, module, exports;
  return (function outerFn(first, second, third) {
    function recursion(number) {
      if (!second[number]) {
        if (!first[number]) {
          var error = new Error("Cannot find module '" + number + "'");
          throw error.code = "MODULE_NOT_FOUND", error
        }
        var module = second[number] = {
          exports: {}
        };
        first[number][0].call(module.exports, function (key) {
          var value = first[number][1][key];
          return recursion(value ? value : key)
        }, module, module.exports, outerFn, first, second, third)
      }
      return second[number].exports//在react实例化的过程中,这行代码不但因获取依赖而多次执行,而且还因获取react实例而最后执行。
    }
    for (var number = 0; number < third.length; number++) recursion(third[number]);//fn(16)第1次执行,执行结果没有变量接收
    return recursion //执行到这,整个逻辑就快结束了。前两行可以合并为一行:return recursion(third[0]),同时下面的"(48)"应当删掉。 
  })({ 2: [function (_dereq_, module, exports) { var thisVar = _dereq_(138) }, { "25": 25, "30": 30 }], }, {}, [16])(16)// fn(16)第2次执行,因为n[num]为真,所以直接返回n[num].exports并被挂在g.React上 
});
 
九、ant-design-pro脚手架的构成
Pro的底座是umi,umi是一个(基于)webpack之上的(自动化)整合工具。
Pro的核心是umi,umi的核心是webpack。
1、web 技术
2、Umi-前端应用框架(可整个或部分复用的软件)
(1)Node.js 前端开发基础环境
(2)Webpack 前端必学必会的打包工具
(3)React Router 路由库,被dva内置
(4)proxy 反向代理工具
(5)dva 轻量级的应用框架(可整个或部分复用的软件)
(6)fabric 严格但是不严苛的 lint 规则集
(7)TypeScript 带类型的 JavaScript
3、Ant Design 前端组件库
4、ProComponents 模板组件
5、useModel 简易数据流
6、编译时和运行时
(1)编译时,环境是node环境,可以使用fs,path等功能;没有使用webpack,不能使用jsx,不能引入图片
(2)运行时,编译完成,开始在浏览器环境运行,不能使用fs、path,有跨域的问题;这个环境被webpack编译过,可以写jsx,导入图片
7、Umi的插件
(1)plugin-access,权限管理
(2)plugin-analytics,统计管理
(3)plugin-antd,整合 antd UI 组件
(4)plugin-initial-state,初始化数据管理
(5)plugin-layout,配置启用 ant-design-pro 的布局
(6)plugin-locale,国际化能力
(7)plugin-model,基于 hooks 的简易数据流
(8)plugin-request,基于 umi-request 和 umi-hooks 的请求方案
8、Umi其它
(1)配置:开发配置和(浏览器)运行配置
(2)路由:配置路由和约定式路由
(3)插件:id和key,每个插件都会对应一个id和一个key,id是路径的简写,key是进一步简化后用于配置的唯一值。

十、前端路由:url有变化,但不向后台发送请求,
1、它的作用是 
(1)记录当前页面的状态; 
(2)可以使用浏览器的前进后退功能; 
2、hash模式帮我们实现这两个功能,因为它能做到: 
(1)改变url且不让浏览器向服务器发出请求; 
(2)监测 url 的变化; 
(3)截获 url 地址,并解析出需要的信息来匹配路由规则。 
3、history 模式改变 url 的方式会导致浏览器向服务器发送请求。
4、react前端路由触发条件
(1)<Link to={item.url}>{item.location}</Link>                         
(2)browserHistory.push('/aaa')