React学习之state与生命周期

说明:本系列所有demo代码的github地址为:https://github.com/Brucewu998/react.js-learning,笔者会不断更新这些代码,本篇代码在目录下demo-05文件夹下。

React学习之组件与props这一节中,讲述了React相关的传值机制props,我们知道React对props由严格的保护机制,一旦给定值,在组件中是不允许改变的;在很多场合中,组件的内容需要根据数据的刷新而刷新,这个时候就可以用到React提供的State,在这里称之为状态机,State与props都是React的私有的,但不同的是,State是完全受控于组件的,所定义的属性值可以根据需求而改变,并在虚拟DOM上同步更新。在React中,state的创建方式为:

class MyComponent extends React.Component {
    constructor(props) {
        super(props);
        this.state = { // 状态机
            value: "Hello"
        }
     }
}

由上面代码可知,利用ES6的class继承方法super,可以将props传递到React.Component的构造函数中。

这里我们以一个更详细的例子来看React的state(状态机)和生命周期:

class Clock extends React.Component {
      constructor(props) {
          super(props);
          this.state = { // 状态机
              date: new Date()
          }
      }

      componentDidMount() {
          this.timerID = setInterval(
              () => this.tick(),
                    1000
           )
      }

      tick() {
          this.setState({ // setState用于更新组件的state
              date: new Date()
          });
      }

      componentWillUnmount() {
          clearInterval(this.timerID);
      }

      render() {
          return (
              <div>
                  <h1>现在的时间:</h1>
                  <h2 className="h2">{ this.state.date.toLocaleTimeString() }</h2>
              </div>
          )
      }
}

上面的代码,创建了一个计时器组件,在这个计时器组件中,包含了两个方法,componentDidMount和componentWillUnmount,这两个方法称之为生命周期方法,当Clock组件第一次被渲染到DOM中的时候,设置一个计时器,用于不断地更新状态机中的date值,这个阶段在React中称之为挂载(mount),同时,当组件被销毁时,应该释放占用的相应资源,这个时候,componentWillUnmount方法就可以用于清除计时器,这在React中称之为卸载(unmount),将相应占用的资源释放掉。关于组件的生命周期相关可以参考:https://zh-hans.reactjs.org/docs/react-component.html#the-component-lifecycle

上面的代码还实现了一个tick的方法,用于更新date这个值;我们可以注意到,这里用了setState这个方法,这是从React.Component中继承而来的一个用于更新状态机(state)中的值的方法,这个方法一般有两种应用的情况:

this.setState({ 
    date: new Date() //直接更新
});

另外一种是需要给setState传一个回调函数来更新值,这个回调函数将整个状态机state作为参数:

class Clock extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            date: new Date(),
            show: true,
            text: "隐藏"
        }
        this.handleClickShow = this.handleClickShow.bind(this);
    }

    handleClickShow(){
        this.setState(state => ({
            show: !state.show,
            text: !state.show ? "隐藏" : "显示"
        }))
    }
}

那么为什么要用回调函数呢?因为在鼠标或者键盘监听事件中,会存在作用域的问题,往往使得this不是指向当前的组件类,所以在构建该组件类时,如果又涉及到相应监听代码,应该进行这个操作:this.handleClickShow = this.handleClickShow.bind(this),

以保证在这个方法内可以正确的访问到this。

这个demo的完整代码如下,也可以去github中查看代码:demo-05.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="../build/react.dev.js"></script>
    <script src="../build/react-dom.dev.js"></script>
    <script src="../build/brower.min.js"></script>
    <title>Demo-07</title>
</head>
<body>
    <div id="demo-7"></div>
    <script type="text/babel">
        class Clock extends React.Component {
            constructor(props) {
                super(props);
                this.state = { // 状态机
                    date: new Date(),
                    show: true,
                    text: "隐藏"
                }
                this.handleClickShow = this.handleClickShow.bind(this);
            }

            componentDidMount() {
                this.timerID = setInterval(
                    () => this.tick(),
                    1000
                )
            }

            tick() {
                this.setState({ // setState用于更新组件的state
                    date: new Date()
                });
            }

            handleClickShow() {
                this.setState(state => ({
                    show: !state.show,
                    text: !state.show ? "隐藏" : "显示"
                }))
                
            }

            componentWillUnmount() {
                clearInterval(this.timerID);
            }

            render() {
                let isShow = this.state.show;
                let element;
                if (isShow) {
                    element = <h2 className="h2">{ this.state.date.toLocaleTimeString() }</h2>
                } else {
                    element = null;
                }
                return (
                    <div>
                        <button onClick={this.handleClickShow}>{this.state.text}计时器</button>
                        {element}
                    </div>
                )
            }
        }
        ReactDOM.render(
            <Clock />,
            document.getElementById("demo-7")
        )
    </script>
</body>
</html>
<style>
    .h2 {
        color: blue;
    }
</style>

上面的demo中,涉及到了条件渲染的知识,这个后边会做详细的讲解。 

效果:

 

上一篇: React学习之获取真实DOM节点

下一篇:React学习之事件处理​​​​​​​

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值