组件的状态

组件的状态

react hook出来之前,函数式组件是没有自己状态的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ioDwfH1u-1689566540446)(images/image-20220901094407996.png)]

​ jsx 就和原生js编写差不多,所有就当作在定义类,在类方法中使用变量,就要通过this来调用。

​ 主义要写在state中,数据驱动视图,我们想要修改视图无需操作dom,通过setState方法来修改state中的变量。这个可以理解为单向的和vue一样。所谓dom操作想要修改自己显示,还是通过修改数据来实现,所以所有数据驱动的框架,都不用我们自己来渲染dom,框架内部虚拟dom性能更高,我们只用关注数据层即可。

不要直接修改state中的值,必须通过setState方法进行修改

import React from "react"

class HelloC extends React.Component {
  //初始状态
  state = {
    count: 10
  }

  setCount = () => {
    this.setState({
      count:this.state.count + 1
    })
  }
  render () {
    return (
      <div>这是我的第一个类组件! <span onClick={this.setCount}>读取我的属性count: {this.state.count}</span></div>
    )
  }
}

​ 这里的setCount方法 使用的箭头函数,如果不使用箭头函数我们就需要绑定this,

class Foo extends React.Component {
  handleClick () {
    this.setState({ xxx: aaa })
  }

  render() {
    return (
      <button onClick={this.handleClick.bind(this)}>
        Click me
      </button>
    )
  }
}

为何需要手动绑定this,记住我们传入的是一个方法,this.handleClick,而并非执行,只有在执行代码时才会为我们绑定this,所以执行时的this早已不是Foo,bind绑定在执行前将foo当作this传入。

此时this指向Helloc,如果直接调用方法handleClick,里边this肯定是Helloc 但是只是传入方法未调用

其他方式:

在这里插入图片描述

在这里插入图片描述

https://juejin.cn/post/6844904200996913160

主流的写法已经变成了class fields,无需考虑太多this问题

页面直接打印 对象

在这里插入图片描述

  • 原因
    写React的render()时,想直接查看整个state对象的内容,就写了{this.state},然后报错。
    原因是不能直接往{}里放Object
  • 解决
    把放入{}中的变量,格式变为非Object即可。两种方法:
    JSON.stringify(xxx)可以将任意变量字符串化,包括对象格式(但要防止对象的循环引用)。
    多写点代码,原本直接传入一个对象,修改为:一个成员一个成员地传入,如{this.state.name} {this.state.age}

这点和vue不大一样,vue是可以直接打印对象查看的。

React的状态不可变

不要直接修改状态值,而是基于当前状态创建新的状态值。

这叫什么来着,就是比如我们封装一些方法,方法有传入的参数,一个好的方法,应该不会修改传入的参数原始值,如果传入一个引用,修改参数原本对象也会修改.所有我们一般将传入引入数据类型拷贝一份。

import React from "react"

class HelloC extends React.Component {
  //初始状态
  state = {
    count: 10,
    list: [1, 2, 3],
    person: {
      name: 'jack',
      age: 18
    }
  }
  handleClick () {
    console.log(this) //undefined
    this.setState({ count: this.state.count + 1 })
  }
  setCount = () => {
    this.setState({
      count: this.state.count + 1
    })
  }
  //基于当前状态创建新值
  newStatus = () => {
    this.setState({
      count: this.state.count + 1,
      list: [...this.state.list, 4],
      person: {
        ...this.state.person,
        // 覆盖原来的属性 就可以达到修改对象中属性的目的
        name: 'rose'
      }
    })
  }
  render () {
    return (
      <div>
        <div>这是我的第一个类组件! <span onClick={(e) => this.handleClick(e)}>读取我的属性count: {this.state.count}</span></div>
        <div>这是我的第一个类组件! <span onClick={this.setCount}>读取我的属性count: {this.state.count}</span></div>
        <div>这是我的第一个类组件! <span onClick={this.newStatus}>读取我的属性count: {this.state.list}{JSON.stringify(this.state.person)}</span></div>
      </div>
    )
  }
}

构造函数是唯一可以给 this.state 赋值的地方。

React 的状态不可变本质上是引用不可变,因为对于 JavaScript 来说,对象是一种引用类型。在你 setState 后,React 会对新旧两个状态进行浅比较,因为 state 是引用类型,所以 React 会比较新旧 state 的引用,只有比较结果为 false,才会进行重新渲染。

所以说,你每次 setState 替换新的对象,其实质是替换对象的引用,让 React 感知到 state 的变化,React 才会进行重新渲染。

官方文档:https://reactjs.org/docs/optimizing-performance.html#avoid-reconciliation

说实话感觉和vue不能检测到data里对象属性改变一样,vue里通过set方法来告知vue进行重新渲染。

而react直接将整个对象重新赋值这样,检测到对象改变,整个肯定会重新渲染,感觉性能没有提升继续往后看吧

当你调用 setState() 的时候,React 会把你提供的对象合并到当前的 state。

这里合并仅仅是浅合并,也就是只合并第一层

React源码中,使用了Object.assign()方法,对preState和更新后的State做了一个合并。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值