22.2、react生命周期与react脚手架(二)

一.类:es6
<script type="text/babel">class Person{
    age = 10;
    constructor(name){
        this.name = name;
        //this.age = 10;
    }
    getName(){
        return this.name;
    }
    getAge(){
        return this.age;
    }
}
let p = new Person("aaa");
console.log(p.getName());
console.log(p.getAge());
</script>
res:
二.生命周期函数
组件生命周期概述
1.初始化
在组件初始化阶段会执行
- constructor
 - static getDerivedStateFromProps()
 - componentWillMount() / UNSAFE_componentWillMount()
 - render()
 - componentDidMount()
 
2.更新阶段
props或state的改变可能会引起组件的更新,组件重新渲染的过程中会调用
以下方法:
- componentWillReceiveProps() / UNSAFE_componentWillReceiveProps()
 - static getDerivedStateFromProps()
 - shouldComponentUpdate()
 - componentWillUpdate() / UNSAFE_componentWillUpdate()
 - render()
 - getSnapshotBeforeUpdate()
 - componentDidUpdate()
 
3.卸载阶段
componentWillUnmount()
4.错误处理
componentDidCatch() 同Vue的错误函数
子级不能捕获自己的错误,只能父级捕获子级的错误 —— 冒泡
参考文献:
https://reactjs.org/docs/react-component.html
https://blog.csdn.net/qq_29311407/article/details/79861522
constructor init
| react | vue | 
|---|---|
| componentWillMount | beforeMount | 
| componentDidMount | mounted | 
| componentWillUpdate | beforeUpdate | 
| componentDidUpdate | updated | 
| render 渲染 | |
| componentWillUnmount | beforeDistory | 
| 没有componentDidlUnmount | distoryed | 
| componentWillReceiveProps(props,state)组件属性更新 —— 状态不会监听 | |
| UNSAFE_componentWillReceiveProps(nextProps) | |
| shouldComponentUpdate(nextProps, nextState) 组件属性和状态更新 | 
react                            vuecomponentWillMount   =      beforeMount
componentDidMount    =      mounted
componentWillUpdate     =      beforeUpdate
componentDidUpdate      =      updated
render  渲染
componentWillUnmount     =     beforeDistory
没有componentDidlUnmount  =    distoryed
componentWillReceiveProps(props,state)  组件属性更新 —— 状态不会监听 
UNSAFE_componentWillReceiveProps(nextProps)
shouldComponentUpdate(nextProps, nextState)      组件属性和状态更新
顺序:
1.初始化:
1、constructor
2、componentWillMount(即将被淘汰的方法)、UNSAFE_componentWillMount
(顺序:先执行componentWillMount再执行UNSAFE_componentWillMount)
3、render
4、componentDidMount
5、ReactDom.render(1,2,fn);
2.更新的顺序:
属性更新、状态更新
1.1 componentWillReceiveProps 属性
1.2 shouldComponentUpdate 状态
—————— 特别: 有返回值 true/false
 	         true继续往下执行
false终止渲染
2、componentWillMount
3、render
4、componentDidMount
componentWillUpdate 消失 ==>替患者 UNSAFE_componentWillUpdate
3.销毁:释放资源 比如定时器 对象置空null
componentWillUnmount
1、通过原生删除节点的方式不会触发钩子函数
2、必须用过react自身的方式进行释放
ReactDOM.unmountComponentAtNode(container)
切换组件
案例:
exp1:
<script type="text/babel">class Test extends React.Component{
    constructor(...args){
        super(...args);
        this.state = {a:12,b:5};
        //初始化 属性 和数据 内部的属性和函数 只会调用一次
        console.log("init constructor",this.state,this.props);
    } 
    componentWillMount(){
        //原生dom 渲染之前 做数据交换
        console.log("componentWillMount",this.state,this.props);
    }
    componentDidMount(){
        //挂载中 写入页面的dom
        console.log("componentDidMount"); 
    }
    render(){
        //正在渲染页面数据—— 虚拟dom
        console.log("render"); 
        return <div>
            生命周期
        </div>
    }
}
ReactDOM.render(
    <Test name="aaa"/>,
    document.getElementById("app"),
    function(){
        console.log("最终渲染完成了");//只会调用一次
    }
);
</script>
res:
exp2:
1.
<script type="text/babel">class Test extends React.Component{
    constructor(...args){
        super(...args);
    } 
    componentWillUnmount(){
        console.log("componentWillUnmount");
    }
    distory(){
        let oApp = document.getElementById("app");
        //document.body.removeChild(oApp);
        ReactDOM.unmountComponentAtNode(oApp);
    }
    render(){
        //正在渲染页面数据—— 虚拟dom
        console.log("render"); 
        return <div>
            生命周期<input onClick={this.distory.bind(this)} type="button" value="销毁" />
        </div>
    }
}
ReactDOM.render(
    <Test/>,
    document.getElementById("app")
);
</script>
res:
<script type="text/babel">class CompA extends React.Component{
    constructor(...args){
        super(...args);
    } 
    componentWillUnmount(){
        console.log("CompA------componentWillUnmount");
    } 
    render(){
        return <div>组件A </div>
    }
}
class CompB extends React.Component{
    constructor(...args){
        super(...args);
    } 
    componentWillUnmount(){
        console.log("CompB------componentWillUnmount");
    } 
    render(){
        return <div>组件B </div>
    }
}
let i = 0;
document.onclick = function(){
    i++;
    ReactDOM.render(
        i%2==0?<CompA/>:<CompB/>,
        document.getElementById("app")
    );
};
</script>
res:
exp3:
<script type="text/babel">class Clock extends React.Component{
    timer = null;
    state = {a:12,iH:"00",iM:"00",iS:"00"};
    componentDidMount(){
        this.tick();
        this.timer = setInterval(()=>{
            this.tick();
        },1000);
    }
    componentWillUpdate(){
       console.log("componentWillUpdate即将更新");
    } 
    componentDidUpdate(){
        console.log("componentDidUpdate更新完成");
     } 
    componentWillUnmount(){
        clearInterval(this.timer);
    } 
    tick(){
        let oDate = new Date();
        this.setState({
            iH:this.addZero(oDate.getHours()),
            iM:this.addZero(oDate.getMinutes()),
            iS:this.addZero(oDate.getSeconds()),
        });
    }
    addZero(n){
        return n < 10?`0${n}`:`${n}`;
    }
    render(){
        console.log("render...正在渲染");
        return <div>
            <span>{this.state.iH}</span>:
            <span>{this.state.iM}</span>:
            <span>{this.state.iS}</span>
            <hr />
            <span>{this.state.a}</span>
        </div>
    }
}
ReactDOM.render(
    <Clock/>,
    document.getElementById("app"),
    function(){
        console.log("最终渲染完成了");//只会调用一次
    }
);
</script>
res:
exp4:
<script type="text/babel">class Parent extends React.Component{
    state = {
        name:Math.random()
    }
    fn(){
        this.setState({
            name:Math.random()
        });
    }
    render(){
        return <div>父组件 <input onClick={this.fn.bind(this)} type="button" value={"按钮"}/>
            <Child name={this.state.name}/>
        </div>
    }
}
class Child extends React.Component{
    componentWillUpdate(){
        console.log("2.componentWillUpdate即将更新");
     } 
    componentDidUpdate(){
         console.log("4.componentDidUpdate更新完成");
    }  
    componentWillReceiveProps(){
        console.log("1.1.componentWillReceiveProps组件属性更新");
    }
    shouldComponentUpdate(){
        console.log("1.2.shouldComponentUpdate组件属性和状态更新");
        return true;
    }
    render(){
        console.log("3.render...正在渲染");
        return <div>子组件——{this.props.name}</div>
    }
}
ReactDOM.render(
    <Parent />,
    document.getElementById("app"),
    function(){
        console.log("最终渲染完成了");//只会调用一次
    }
);
</script>
res:
<script type="text/babel">class Test extends React.Component{
    state = {
        name:Math.random()
    }
    fn(){
        this.setState({
            name:Math.random()
        });
    }
    componentWillUpdate(){
        console.log("2.componentWillUpdate即将更新");
     } 
    componentDidUpdate(){
         console.log("4.componentDidUpdate更新完成");
    }  
    componentWillReceiveProps(){
        console.log("1.componentWillReceiveProps组件属性更新");
    }
    render(){
        console.log("3.render...正在渲染");
        return <div>{this.state.name}<input onClick={this.fn.bind(this)} type="button" value={"按钮"}/></div>
    }
}
ReactDOM.render(
    <Test />,
    document.getElementById("app")
);
</script>
res:
<script type="text/babel">class Test extends React.Component{
    state = {
        name:Math.random()
    }
    fn(){
        this.setState({
            name:Math.random()
        });
    }
    componentWillUpdate(){
        console.log("2.componentWillUpdate即将更新");
     } 
    componentDidUpdate(){
         console.log("4.componentDidUpdate更新完成");
    }  
    shouldComponentUpdate(){
        console.log("1.shouldComponentUpdate组件属性和状态更新");
        return false;
    }
    render(){
        console.log("3.render...正在渲染");
        return <div>{this.state.name}<input onClick={this.fn.bind(this)} type="button" value={"按钮"}/></div>
    }
}
ReactDOM.render(
    <Test />,
    document.getElementById("app")
);
</script>
res:
<script type="text/babel">class Parent extends React.Component{
    state = {
        name:Math.random()
    }
    fn(){
        this.setState({
            name:Math.random()
        });
    }
    render(){
        return <div>父组件 <input onClick={this.fn.bind(this)} type="button" value={"按钮"}/>
            <Child name={this.state.name}/>
        </div>
    }
}
class Child extends React.Component{ 
    state = {a:1,b:2}; 
    componentWillReceiveProps(props,state){
        console.log("1.1.componentWillReceiveProps组件属性更新",props,state);
        //在这个方法中调用setState()不会起作用,是由于他在render()前被调用
        this.setState({
            a:Math.random(),
            b:Math.random()
        });
    }
    UNSAFE_componentWillReceiveProps(props,state){
        console.log("1.1.UNSAFE_componentWillReceiveProps组件属性更新",props,state);
        //在这个方法中调用setState()不会起作用,是由于他在render()前被调用
        this.setState({
            a:Math.random(),
            b:Math.random()
        });
    } 
    shouldComponentUpdate(props,state){
        console.log("1.2.shouldComponentUpdate组件属性和状态更新",props,state);
        return true;
    }
    render(){
        return <div>子组件——{this.props.name}</div>
    }
}
ReactDOM.render(
    <Parent />,
    document.getElementById("app")
);
</script>
res:
exp5:
<script type="text/babel">class Parent extends React.Component{
    state = {
        name:Math.random()
    }
    fn(){
        this.setState({
            name:Math.random()
        });
    }
    render(){
        return <div>父组件 ----{this.state.name}<input onClick={this.fn.bind(this)} type="button" value={"按钮"}/>
            <Child name={this.state.name}/>
        </div>
    }
}
class Child extends React.Component{
    state = {
        name:this.props.name
    };
    static getDerivedStateFromProps(nextProps, prevState){
        console.log("1getDerivedStateFromProps",nextProps, prevState);
        return true;
    } 
    componentWillReceiveProps(){
        console.log("2componentWillReceiveProps");
    } 
    render(){
        console.log("3.render...正在渲染");
        return <div>子组件——{this.props.name}——{this.state.name}</div>
    }
}
ReactDOM.render(
    <Parent />,
    document.getElementById("app"),
    function(){
        console.log("最终渲染完成了");//只会调用一次
    }
);
</script>
res:
exp6:
<script type="text/babel">class Test extends React.Component{
    constructor(...args){
        super(...args);
        this.state = {a:12,b:5};
        //初始化 属性 和数据 内部的属性和函数 只会调用一次
        console.log("init constructor",this.state,this.props);
    } 
    UNSAFE_componentWillMount(){
        //原生dom 渲染之前 做数据交换
        console.log("UNSAFE_componentWillMount",this.state,this.props);
    }
    componentWillMount(){
        //原生dom 渲染之前 做数据交换
        console.log("componentWillMount",this.state,this.props);
    }
    componentDidMount(){
        //挂载中 写入页面的dom
        console.log("componentDidMount"); 
    }
    render(){
        //正在渲染页面数据—— 虚拟dom
        console.log("render"); 
        return <div>
            生命周期
        </div>
    }
}
ReactDOM.render(
    <Test name="aaa"/>,
    document.getElementById("app"),
    function(){
        console.log("最终渲染完成了");//只会调用一次
    }
);
</script>
res:
exp7:
<script type="text/babel">class Parent extends React.Component{
    state = {
        name:Math.random()
    }
    fn(){
        this.setState({
            name:Math.random()
        });
    }
    render(){
        return <div>父组件 <input onClick={this.fn.bind(this)} type="button" value={"按钮"}/>
            <Child name={this.state.name}/>
        </div>
    }
}
class Child extends React.Component{
    //UNSAFE_componentWillReceiveProps用来替代componentWillReceiveProps
    componentWillReceiveProps(){
        console.log("1.1.componentWillReceiveProps组件属性更新");
    }
    UNSAFE_componentWillReceiveProps(){
        console.log("1.2.UNSAFE_componentWillReceiveProps组件属性和状态更新");
    }
    render(){
        console.log("3.render...正在渲染");
        return <div>子组件——{this.props.name}</div>
    }
}
ReactDOM.render(
    <Parent />,
    document.getElementById("app"),
    function(){
        console.log("最终渲染完成了");//只会调用一次
    }
);
</script>
res:
exp8:
<script type="text/babel">class Parent extends React.Component{
    //throw new Error("parent");
    state = {
        name:Math.random()
    }
    fn(){
        this.setState({
            name:Math.random()
        });
    }
    componentDidCatch(){
        console.log("Parent ----- componentDidCatch");
    } 
    render(){
        return <div>父组件 <input onClick={this.fn.bind(this)} type="button" value={"按钮"}/>
            <Child name={this.state.name}/>
        </div>
    }
}
class Child extends React.Component{
    //throw new Error("child");
    componentDidCatch(){
        console.log("child ----- componentDidCatch");
    } 
    render(){
        throw new Error("child");
        console.log("3.render...正在渲染");
        return <div>子组件——{this.props.name}</div>
    }
}
ReactDOM.render(
    <Parent />,
    document.getElementById("app"),
    function(){
        console.log("最终渲染完成了");//只会调用一次
    }
);
</script>
res:
创建reactapp
方法一、 npx create-react-app myreact
方法二、 1. cnpm i -g create-react-app
2. create-react-app myreact
cd myreact
npm start
vue-cli:
1、vue-cli2.x vue init webpack myvue
2、vue-cli3.x vue create myvue —— vue.config.js
入口文件:main.js
静态文件:vue-cli2.x    static/
vue-cli3.x public/
组件: .vue template/script/style
react:
  cnpm i -g create-react-app
create-react-app myreact
入口文件:index.js
静态文件:public/
组件: .js .css
import "./xxx.css"
react 安装:react, react-dom, and react-scripts —— 后台
webpack/babel...
%PUBLIC_URL%/---> public/
改端口
两种方法:
1、myreact\node_modules\react-scripts\scripts\start.js
2、工程文件 package.json
"start": "set port=8888 && react-scripts start",要新建两个目录:
1、components
2、assets
静态文件—— 文件会打包
路由: cnpm i -S react-router-dom
https://reacttraining.com/ 官网 http://reacttraining.cn/
http://react-china.org/t/react-router4/15843
http://react-guide.github.io/react-router-cn/docs/API.html
http://react-guide.github.io/react-router-cn/
jsonp:
http://api.douban.com/v2/movie/in_theaters?callback=xxx&city=北京
subjects
jQuery的ajax没有跨域功能 集成jsonp
exp1:
<script type="text/babel">class MoveBox extends React.Component{
    state = {
        id:1,
        city:"北京"
    }
    /*//第二种
    shouldComponentUpdate(nextProps, nextState){
        console.log(2222,this.state, nextState);
        return true;
    }**/
    fn(data){
        //第三种
        console.log("fn",this.state, data);
        if(this.state.city == data.city)return;
        this.setState({
            id : data.id,
            city:data.city
        });
    }
    render(){
        return <div>
            {
                this.props.arr.map(item=><input 
                className={this.state.id==item.id?"active":""} 
                key={item.id} 
                type="button" 
                onClick={this.fn.bind(this,item)}
                value={item.city}/>)
            }
            <BoxList city={this.state.city}/>
        </div>
    }
}
class BoxList extends React.Component{
    state = {
        movies:[]
    };
    componentDidMount(){
        this.getMovies();
    }
    /*
    shouldComponentUpdate(nextProps, nextState){
        console.log(111,nextProps, nextState);
        return true;
    }*/
    UNSAFE_componentWillReceiveProps(props){
        /*方法1
        console.log(props,this.props);
        if(props.city == this.props.city)return;
        */
        this.getMovies();
    }
    getMovies(){
        $.ajax({
            url:"http://api.douban.com/v2/movie/in_theaters",
            data:{
                city:this.props.city
            },
            dataType:"jsonp",
            success:(res)=>{
                console.log(res);
                this.setState({
                    movies:res.subjects
                });
            }
        });
    }
    render(){
        return <ul>
           {
            this.state.movies.map(item=><li key={item.id}>{item.title}</li>)
           }
        </ul>
    }
}
let arr = [
    {id:1,city:"北京"},
    {id:2,city:"上海"},
    {id:3,city:"深圳"},
    {id:4,city:"青岛"}
];
ReactDOM.render(
    <MoveBox arr={arr} />,
    $("#app")[0]
);
</script>
exp2:
<script type="text/babel">class MoveBox extends React.Component{
    state = {...this.props.arr[0]};
    fn(data){
        console.log(this);
        //第三种
        //console.log("fn",this.state, data);
        if(this.state.city == data.city)return;
        this.setState({
            id : data.id,
            city:data.city
        });
    }
    render(){// 
        return <div>
            {/*
                this.props.arr.map(item=><input 
                className={this.state.id==item.id?"active":""} 
                key={item.id} 
                type="button" 
                onClick={this.fn.bind(this,item)}
                value={item.city}/>)
            }
            */}
            <BoxTitle arr={this.props.arr} parent={this} fn={this.fn} />
            <BoxList city={this.state.city}/>
        </div>
    }
}
class BoxTitle extends React.Component{
    state = {...this.props.arr[0]}
    render(){
        return <div>
            {
                this.props.arr.map(item=><input 
                className={this.state.id==item.id?"active":""} 
                key={item.id} 
                type="button" 
                onClick={this.props.fn.bind(this.props.parent,item)}
                value={item.city}/>)
            }
        </div>
    }
}
class BoxList extends React.Component{
    state = {
        movies:[]
    };
    componentDidMount(){
        this.getMovies();
    }
    UNSAFE_componentWillReceiveProps(props){
        this.getMovies();
    }
    getMovies(){
        $.ajax({
            url:"http://api.douban.com/v2/movie/in_theaters",
            data:{
                city:this.props.city
            },
            dataType:"jsonp",
            success:(res)=>{
                console.log(res);
                this.setState({
                    movies:res.subjects
                });
            }
        });
    }
    render(){
        return <ul>
           {
            this.state.movies.map(item=><li key={item.id}>{item.title}</li>)
           }
        </ul>
    }
}
let arr = [
    {id:1,city:"北京"},
    {id:2,city:"上海"},
    {id:3,city:"深圳"},
    {id:4,city:"青岛"}
];
ReactDOM.render(
    <MoveBox arr={arr} />,
    $("#app")[0]
);
</script>
https://reactjs.org/docs/react-component.html#defaultprops
以上是 22.2、react生命周期与react脚手架(二) 的全部内容, 来源链接: utcz.com/z/383587.html
