React学习笔记四-state

此文章是本人在学习React的时候,写下的学习笔记,在此纪录和分享。此为第四篇,主要介绍react中的state。

1.state(状态)

1.1state简介

存在state(状态)的组件称为复杂组件,反之称为简单组件。

何为状态呢?举例,人是有状态的,状态影响着人的行为举止。组件也是有状态的,数据存放在状态内,状态驱动着页面的展示。

        1.state是组件对象中最重要的属性,值是对象(可以包含多个key-value的组合)

        2.组件被称为“状态机”,通过更新组件的state来更新对应的页面显示(重新渲染组件)

        3.在类定义的组件中,state是其三大核心属性之一,另外两个是props,refs。

1.2案例:炎热与凉爽的切换

1.2.1非实时切换

我们先创建类式组件Weather,在reander函数内打印一下this指向。

如图所示,我们打印出了Weather这个实例对象,在实例对象内存在state,而且state是一个对象。如果我们没有设置state,那么它就是一个空对象,在代码内我们写了:this.state = {isHot:true},所以现在state内就有了isHot:true这条数据。

 在render函数内的构建虚拟dom中,我们使用三目运算符,根据this.state.isHot是true还是false,来分别显示炎热或者凉爽。

代码:

<!-- 准备好容器 -->
    <div id="test"></div>
<!-- 引入react库,以下依次为核心库,操作dom的库和babel(将jsx转为js的库),此顺序不可有错误 -->
    <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 type="text/babel">//写为babel格式,否则识别为普通js文件
        class Weather extends React.Component {
            constructor(props){//使用构造器和super关键字,从父类继承props
                super(props)
                this.state = {isHot:true}//为实例中的State
            }
            render() {
                console.log(this);
                return <h1>今天天气很{this.state.isHot?'炎热':'凉爽'}</h1>
            }
        }
        ReactDOM.render(<Weather/>, document.getElementById('test'))
    </script>

显示结果:

 如果我们手动设置this.state = {isHot:false}

结果:

1.2.2React中的为元素绑定事件

 现在我们要实现,炎热和凉爽的动态切换,首先要对元素绑定事件。众所周知,原生js中为元素添加事件的办法有三种,元素.onclick,元素.addEventListener(’事件名字‘,函数体)和<div οnclick='demo()'>按钮</div>。我们使用第三种,但注意写成<div onClick={demo}>按钮</div>,在react中事件名称要写成小驼峰的形式,并且函数名后不可以加小括号,否则会直接调用函数,在dom渲染在界面的时候直接把函数的返回值跟着一起渲染一次。

代码更改部分如下:

 class Weather extends React.Component {
            constructor(props){//使用构造器和super关键字,从父类继承props
                super(props)
                this.state = {isHot:false}//为实例中的State
            }
            render() {
                console.log(this);
                //为h1标签添加点击事件和点击后触发的函数demo
                return <h1 onClick={demo}>今天天气很{this.state.isHot?'炎热':'凉爽'}</h1>
            }
        }
        ReactDOM.render(<Weather/>, document.getElementById('test'))
        function demo(){//点击事件的函数
            console.log('此标签被点击');
        }

效果如下:

 1.2.3实现动态切换

学习react,我们对原型,类,实例对象和this指向这部分知识,应该掌握牢固。

        首先我们要知道state(状态)不可以直接的更改,要借助一个内置的api--setState去更改,如果我们直接去更改。如:this.state.isHot = !isHot这种写法,是没有作用的。必this.setState({isHot:!isHot})这样写,才能有效果。而且此api更新state是合并,而并非覆盖,不会丢失其他原有数据。

        其次我们在构造器中,在Weather原型链上寻找changeWeather这个函数,并改变其this指向,赋值给demo使其存在在Weather的实例对象上,也就是this.demo=this.changeWeather.bind(this)这行代码,这样在rendr中虚拟dom添加点击事件的回调函数中,使用this.demo就可以直接在触发点击时调用我们放在实例对象上的changeWeather函数,就不会去沿着原型链去寻找changeWeather,直接选择本实例对象上的changeWeather,解决了类中系统自动开启局部严格模式导致this指向underfined,调用不到changeWeather的情况。

        最后是构造器,render和changeWeather函数调用几次的问题。在创建的类实例化的时候,构造器会调用一次,之后均不会被调用。此时render去生成虚拟dom被调用一次,数据更新时render均会被调用一次。changeWeather这个回调函数控制数据的更新,所以每次我们触发点击事件,state状态进行更新,那么changeWeather就会被调用。

代码如下:

class Weather extends React.Component {
            //构造器调用,仅仅1次
            constructor(props){//使用构造器和super关键字,从父类继承props
                super(props)
                //初始化状态
                this.state = {isHot:false}//为实例中的State
                //在Weather原型链上寻找changeWeather这个函数,并改变其this指向,赋值给demo使其存在在Weather的实例对象上
                this.demo = this.changeWeather.bind(this)
            }
            //render调用 1+n次,1次是初始化那次,n次是数据更新了几次
            render() {
                //结构赋值
                const {isHot} = this.state
                //为h1标签添加点击事件和相应的回调函数changeWeather
                //此处写成this.demo,直接调用实例对象上的changeWeather函数
                return <h1 onClick={this.demo}>今天天气很{isHot?'炎热':'凉爽'}</h1>
            }
            //changeWeather是,点几次它就调用几次
            changeWeather(){
                //changeWeather放在Weather的原型对象上,供实例调用
                //由于changeWeather是作为onClick的回调,所以不是通过实例调用的,是直接调用
                //类中的方法默认开启了局部的严格模式,所以changeWeather中的this为underfined
                const isHot = this.state.isHot
                //状态不可以直接的更改,要借助一个内置的api(setState)去更改
                // 这行就是直接更改:this.state.isHot = !isHot
                this.setState({isHot:!isHot})//使用setState来更改状态,且更新是一种合并不是替换,不会丢失原有数据
            }
        }
        ReactDOM.render(<Weather/>, document.getElementById('test'))

效果就是点击文字,炎热和凉爽二字会来回切换。

1.3state代码精简

上面的代码写的实在是太繁琐了,在使用react时用不着那么麻烦,所以我们对上面的代码进行精简书写。

首先我们去掉构造器,直接在类里面写赋值语句,与在构造器中写一样,直接在实例对象中存在。

然后我们把changeWeather使用箭头函数属性,并且赋值给changeWeather。箭头函数没有自己的this,在涉及this指向时候,其this和其外侧函数一致,所以下方的this.setState({isHot:!isHot})中的this直接是指向Weather的实例对象,保证直接更改实例对象中的state。

代码如下:

<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 type="text/babel">
        class Weather extends React.Component {
            state = {isHot:false}//直接在类里面写赋值语句,与在构造器中写一样
            render() {
                const {isHot} = this.state
                return <h1 onClick={this.demo}>今天天气很{isHot?'炎热':'凉爽'}</h1>
            }
            //自定义函数,必须使用赋值语句和箭头函数
            changeWeather = ()=>{//此处必须使用箭头函数,箭头函数没有自己的this,在涉及this指向时候,其this和其外侧函数一致
                const isHot = this.state.isHot
                this.setState({isHot:!isHot})//所以此处this指向,是Weather的实例对象
            }
        }
        ReactDOM.render(<Weather/>, document.getElementById('test'))
    </script>

1.4state总结

        1.state是组件对象中最重要的属性,值是对象(可以包含多个key-value的组合)

        2.组件被称为“状态机”,通过更新组件的state来更新对应的页面显示(重新渲染组件)

        3.在类定义的组件中,state是其三大核心属性之一,另外两个是props,refs。

强烈注意:

        1.组件中render方法中的this为组件实例对象。

        2.如何解决组件内自定义方法this指向为undefined?

                (1),强制绑定this,通过函数对象的bind

                (2),使用箭头函数

        3.状态数据,不能直接修改或者更新,使用一个内置的api(setState)去更改

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啊啊啊啊啊威

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值