React学习笔记四-state

news2024/11/18 3:38:16

此文章是本人在学习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)去更改

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/546390.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TCL表达式

目录 操作数 运算符和优先级 数学函数 操作数 TCL 表达式的操作数通常是整数或实数。整数一般是十进制的&#xff0c; 但如果整数的第一个字符是 0(zero)&#xff0c;那么 TCL 将把这个整数看作八进制的&#xff0c;如果前两个字符是 0x 则这个整数被看作是十 六进制的。TC…

I2C项目问题总结

1、项目里面用到哪些接口&#xff1f;都是怎么用的&#xff1f; 项目里面用到了rkv_i2c_if、lvc_i2c_if、lvc_apb_if。rkv_i2c_if用来将DUT内部的intr中断信号、debug信号、ic_en使能信号、i2c和apb的时钟复位信号引出&#xff0c;在接口中声明了一个大位宽信号用来表示intr中…

分布式消息中间件RocketMQ的工作原理

RocketMQ 工作原理 消息的生产 消息的生产过程 ​ Producer可以将消息写入到某Broker中的某Queue中&#xff0c;其经历了如下过程&#xff1a; Producer发送消息之前&#xff0c;会先向NameServer发出获取消息Topic的路由信息的请求NameServer返回该Topic的路由表及Broker列…

kubernetes yaml文件|--dry-run导出yaml文件

kubernetes yaml文件|--dry-run导出yaml文件 YAML 语法格式&#xff1a;二 查看 api 资源版本标签三 写一个nignx.yaml文件demo四、编写service服务的资源清单详解k8s中的port五 用–dry-run命令生成yaml资源清单六 将现有的资源生成模板导出写yaml太累怎么办&#xff1f; YAML…

关于FLAME和SMPL模型

英文参考文献&#xff1a;https://medium.com/offnote-labs/3d-face-and-body-reconstruction-95f59ada1040 一个训练好的FLAME模型的输入是一个参数向量&#xff0c;包括形状参数、姿势参数和表情参数。这些参数分别控制人脸的身份特征、头部的旋转和平移、面部的表情变化。一…

算法设计与分析:线性规划问题和单纯形算法(作业-必做)(头歌实验)

第1关&#xff1a;单纯性算法解一般线性方程组 任务描述 本关任务&#xff1a;编写一个利用两阶段单纯性算法求一般线性规划的程序。 相关知识 单纯形算法的第1步&#xff1a;选出使目标函数增加的非基本变量作为入基变量。 查看单纯形表的第 1 行&#xff08;也称之为z行…

UnityVR--Managers--对象池1

本篇中使用的API&#xff1a;gameObject.CompareTag("标签")、UnityEvent()事件管理、ObjectPool<GameObject>&#xff08;&#xff09;对象池 参照unity官方教程&#xff1a;Hi ObjectPool 目录 1. 应用场景 2. 对象池的原理 3. 查看资源消耗情况 4. 不使用…

mysql 备库延迟问题

备库延迟原因&#xff1a; log传送开销小&#xff0c;消费relay log 超时 备库性能不如主库 备库承担更多SQL分析 主库是多线程执行&#xff0c;备库是单线程执行解析relay log 处理方法&#xff1a; 主备使用相同的机器 备库关闭log实时落盘 增加从库数量&#xff0c;…

Sentinel-2数据下载及处理

数据下载网站&#xff1a;欧空局官网&#xff08;需注册并登录&#xff09; https://scihub.copernicus.eu/dhus/#/home 哨兵2 L1C数据波段信息 哨兵2 L1C数据时间&#xff1a;2015-06-23至now 由于数据量大&#xff0c;考虑服务器压力&#xff0c;哨兵2号数据直接下载的时间跨…

[web安全原理分析]-XXE漏洞入门

前言 XXE漏洞 XXE漏洞全称(XML External Entity Injection)即xml外部实体注入漏洞&#xff0c;XXE漏洞发生在应用程序解析XML输入时&#xff0c;没有禁止外部实体的加载&#xff0c;导致可加载恶意外部文件&#xff0c;造成文件读取、命令执行、内网端口扫描、攻击内网网站、…

头歌计算机组成原理实验—运算器设计(10) 第10关:补码一位乘法器设计

第10关&#xff1a;补码一位乘法器设计 实验目的 学生掌握补码一位乘法运算的基本原理&#xff0c;熟练掌握 Logisim 寄存器电路的使用&#xff0c;能在 Logisim 平台中设计实现一个8*8 位的补码 Booth一位乘法器。 视频讲解 ####实验内容 在 alu.circ 文件中的补码一位乘法…

Linux基础——权限

1. Linux下的用户 在 Linux 操作系统中&#xff0c;有两种主要类型的用户账户&#xff0c;分别是普通用户账户和超级用户账户&#xff08;也称为 root 用户账户&#xff09;。 普通用户账户&#xff08;user&#xff09;是在 Linux 系统上创建的普通账户&#xff0c;可以用于日…

图片隐写(一)

文件隐藏 binwalk binwalk -e filename foremost foremost filename steghide & stegseek Install sudo apt-get install steghidestegseek Use steghide extract -sf filename -p passwordtime stegseek secret.file aaa.txt dd 文本隐藏 二进制文件末尾 or 文…

ffmpeg rtsp解析

一、 rtsp 协议说明 rtsp的协议层级 rtsp 属于应用层&#xff0c; 使用tcp传输&#xff0c;主要是传递服务器的一些信息&#xff0c;实现流连接。播放 暂停 销毁等控制 rtp 实现音视频数据包的发送&#xff0c;通过RTSP等协议的SDP信息协商好了RTP数据包的发送目的和传输方式…

UNIX网络编程卷一 学习笔记 第十四章 高级I/O函数

有3种方式可在涉及套接字的IO操作上设置超时方法&#xff1a; 1.调用alarm&#xff0c;它在指定超时期满时产生SIGALRM信号。此方法涉及信号处理&#xff0c;而信号处理在不同的实现上存在差异&#xff0c;且此方法可能干扰进程中已经执行过的alarm调用&#xff0c;可能使之前已…

【LLM系列之Tokenizer】如何科学地训练一个LLM分词器

1 背景与基础 1.1 为什么需要分词 对于人而言&#xff0c;在我们学会阅读之前&#xff0c;仍然可以理解语言。比如当你开始上学时&#xff0c;即使你不知道名词和动词之间的区别&#xff0c;但是你已经可以和你的同学交谈了&#xff0c;比如“我喜欢吃香蕉”&#xff0c;孩子…

vmware ubuntu突然无法联网的一种解决方案

记录一下vmware突然无法联网的一种解决方案。此法未必适用所有无法联网情形。Good Luck then. 今天使用vmware的ubuntu 18.04时&#xff0c;突然无法联网。Firefox在访问百度时显示“The proxy server is refusing connections”&#xff0c;随即检查了浏览器的proxy设置&#…

详解Jetpack Compose中的状态管理与使用

前言 引用一段官方描述&#xff0c;如下 由于 Compose 是声明式工具集&#xff0c;因此更新它的唯一方法是通过新参数调用同一可组合项。这些参数是界面状态的表现形式。每当状态更新时&#xff0c;都会发生重组。因此&#xff0c;TextField 不会像在基于 XML 的命令式视图中那…

头歌计算机组成原理实验—运算器设计(9)第9关:原码一位乘法器设计

第9关&#xff1a;原码一位乘法器设计 实验目的 学生掌握原码一位乘法运算的基本原理&#xff0c;熟练掌握 Logisim 寄存器电路的使用&#xff0c;能在 Logisim 平台中设计实现一个 8*8位的无符号数乘法器。 视频讲解 ####实验内容 在 alu.circ 文件中的原码一位乘法器子电…

分布式消息中间件RocketMQ概述

RocketMQ 概述 MQ概述 MQ简介 ​ MQ&#xff0c;Message Queue&#xff0c;是一种提供消息队列服务的中间件&#xff0c;也称为消息中间件&#xff0c;是一套提供了消息生产、存储、消费全过程API的软件系统。消息即数据。一般消息的体量不会很大。 MQ用途 在网络上上可以查…