美文网首页React学习笔记
React笔记5(State和生命周期)

React笔记5(State和生命周期)

作者: XKolento | 来源:发表于2018-07-19 17:36 被阅读0次

    回顾:
    根据目前学习内容,更新界面内容的方法为ReactDOM.render()

    //定义一个方法tick,包含组件和渲染
    function tick(){
        const element = <h1>{new Date().toLocalTimeString()}</h1>
        ReactDOM.render(
            element,document.getElementById('root')
        )
    }
    //运行方法,每秒钟重新构建元素和渲染,计时器效果
    setInterval(tick,1000);
    
    本次目的:实现clock组件的封装和可重用

    1.将函数转换成class
    ①创建一个名为React.Component的ES6类
    ②创建一个render()的空方法
    ③把函数体移动到render(){}方法中
    ④在render方法中,使用this.props替换props
    ⑤删除剩余的空函数声明

    class Clock extends React.Component{
        render(){
            return(
                <div>
                      <h1>{this.props.date.toLocaleTimeString()}</h1>
                </div>
            )
        }
    }
    ReactDOM.render(
        <Clock date={new Date()} />,
        document.getElementById('root')
    )
    

    现在Clock被定义为一个类,而不只是一个函数,
    使用类就允许我们使用它的特性,例如局部状态,生命状态钩子。

    1.为了一个类添加局部状态

    ①将date从属性中转移到状态中
    ②在render()方法张使用this.state.date代替this.props.date
    ③添加一个类构造函数来初始化State,类组件应始终用props调用基础构造函数
    ④在Clock组件中,去除date属性

    class Clock extends React.Component{
        constructor(){
            super(props);
            this.state = {date:new Date()};
        }
        render(){
            return(
                <h1>it is {this.state.date.toLocalTimeString()}</h1>
            )
        }
    }
    
    ReactDOM.render(
        <Clock />,document.getElementById('root')
    )
    

    2.将生命周期方法添加到类中

    在具有许多组件的应用程序中,销毁时释放组件所占用的资源非常重要。
    每当Clock 组件加载到DOM中,都会想要用它生成一个定时器,在React中被称为挂载
    同样,每当Clock生成的这个DOM被移除时,就需要清除定时器,这被称为 卸载。
    可以在组件中生命一些方法,当组件 挂载 或者 卸载时执行。

    class Clock extends React.Component{
        constructor(props){
            super(props);
            this.state = {date:new Date()};
        }
        componentDidMount(){
            console.log('挂载开始')
            this.timerID = setInterval(()=>{
                this.tick();
            },1000)
        }
        componentWillUnmounte(){
            console.log('结束')
            clearInterval(this.timerID);
        }
        tick(){
            this.setState({
                date:new Date()
            })
        }
        render(){
            return(
                <div>
                      <h1>{this.state.date.toLocaleTimeString()}</h1>
                </div>
            )
        }
    }
    ReactDOM.render(
        <Clock />,
        document.getElementById('root')
    )
    

    以上的componentDidMount()componentWillUnmount()方法被称为生命周期钩子
    当组件输出到DOM后会执行componentDidMount()方法,这时候适合建立一个定时器
    步骤如下:
    ①当 <Clock /> 被传递给 ReactDOM.render() 时,React 调用 Clock 组件的构造函数。 由于 Clock 需要显示当前时间,所以使用包含当前时间的对象来初始化 this.state 。即this.state={date:new Date()};

    ②React 然后调用 Clock 组件的 render()方法。把React 更新 DOM 以匹配 Clock 的渲染输出。

    ③当 Clock 的输出插入到 DOM 中时,React 调用 componentDidMount()生命周期钩子。 在其中,Clock 组件要求浏览器设置一个定时器,每秒钟调用一次 tick(),此时DOM已经构建好,类似vue的mounted()

    ④浏览器每秒钟调用 tick()方法。 在其中,Clock 组件通过使用包含当前时间的对象调用 setState()来调度UI更新。 通过调用 setState(),React 知道状态已经改变,并再次调用 render()方法来确定屏幕上应当显示什么。 这一次,render()方法中的 this.state.date将不同,所以渲染输出将包含更新的时间,并相应地更新DOM。

    ⑤一旦Clock组件被从DOM中移除,React会调用componentWillUnmount()这个钩子函数,定时器也就会被清除。

    从中可知:

    修改this.state状态需要使用this.setState({})方法,这里有点类似微信小程序的设置方式。

    3.正确的使用状态

    关于this.setState({})的几个重点
    ①更新状态或者this.state中的内容

    this.setState({comment:'hello'}); //正确修改方式
    this.state.comment='hello' //错误方式
    this.state.comment //获取state状态中的内容
    

    ②构造函数是唯一能够初始化this.state的地方
    ③状态的更新可能是异步操作导致的
    React可以将多个setState({})调用合并成一个来提高性能。
    因为this.propsthis.state可能是异步更新的,所以不应该根据这个来计算下一个状态的值,因为可能不是最新的数据。

    这里使用第二种形式
    setState({})接收一个方法,而不是一个对象,其中包含2个参数,先前的状态state作为第一个参数,应用被更新时的props作为第二个参数

    // 错误的方式,计算的结果不是最新的
    this.setState({
      counter: this.state.counter + this.props.increment,
    });
    // 正确的方式
    this.setState((prevState,props)=>{
          counter:prevState.counter+props.increment
    })
    

    4.状态的更新并合并

    当使用this.setState的时候,React会将当前的提供的对象合并到当前状态
    状态中可能包含一些独立的变量

    constructor(props){
        super(props);
        this.state({
            posts:[],
            comment:[]
        })
    }
    

    此时,可以分别调用```this.setState···独立调用他们

      componentDidMount() {
        fetchPosts().then(response => {
          this.setState({
            posts: response.posts
          });
        });
    
        fetchComments().then(response => {
          this.setState({
            comments: response.comments
          });
        });
      }
    

    5.数据的自顶向下流动

    父组件或者子组件都不能知道其他组件是否有状态state,以及组件是被定义为一个class类还是函数。
    除了拥有并且设置他的组件外,其他组件不可访问内部状态。

    组件可以选择将他的状态作为属性传递给其他子组件。通过this.state来获取

    <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
    

    也适用于用户自定义的组件

    <hello date={this.state.date} />
    

    其中hello组件收到的date属性值,并不知道是来自Clock组件的属性还是状态。

    这通常被称为 自顶向下的数据流,或者是单向数据流。任何状态始终只在某些特定的组件中,并且该状态的导出的数据或者UI视图,也只能影响 树 下方的组件。

    DEMO

    为了证明所有组件都是隔离的,先创建一个组件<App />

    class App extends React.Component{
        render(){
            return(
                <div>
                      <Clock />
                      <Clock />
                      <Clock />
                </div>
            )
        }
    }
    
    ReactDOM.render(
        <App />,document.getElementById('root')
    )
    

    其中的每一个<Clock />会建立自己的组件并且独立更新。

    相关文章

      网友评论

        本文标题:React笔记5(State和生命周期)

        本文链接:https://www.haomeiwen.com/subject/ymtapftx.html