前端入门React 三大属性之一 State

理解什么是 state ?

首先 咱们用最通俗易懂的话来理解, 好比 每一个人都有本身的状态 , 每一个人的状态 都会影响 他的行为,react

那么, 咱们将这句话放到 react 中去理解,把人看做是 组件,组件也有本身的状态,组件的状态会影响api

它的页面。markdown

咱们在游览各大网页时,会发现 网页上有一些数据,如我的信息 帐号 以及一些新闻列表等等。 这些都app

是数据, 咱们将这些数据放在了页面上,那么是什么驱动着页面的改变呢? 是数据。 这时候咱们只须要函数

将数据 放入状态 ( state ) 中 ,咱们去更改状态 页面也会随之变化。this

  1. 首先咱们用脚手架建立一个 react 项目

r1.jpg

  1. 启动 项目 进入 src / app.js 修改为以下文件
import React, { Component } from 'react'
​
export default class App extends Component {
  render() {
    console.log(this)
    return (
      <div>
        app组件
      </div>
    )
  }
}
复制代码
  1. 打开 控制台能够看见 以下

r2.jpg

  1. 咱们在 render() 方法中 打印了 this 能够看见在这个组件的实例对象上面。已经有一个 state 了 ( 这就是react 给你准备好的状态 )

如今咱们回到 第一个问题 理解什么是 state ?spa

1 . state 是组件对象最重要的属性 ,值是对象 ( 里面能够包含多个 key : value 的 组合 ) 虽然在初始化看到的是null , 在react以前的版本中 仍是一个 { }3d

2 . 组件被称之为状态机 , 经过更新组件里的 state 来更新对应的页面显示 ( 从新渲染组件 )code

须要注意的地方 : 因有函数时组件与类式组件 react 将状态放到了 实例对象里 函数时组件 连this都没有 哪儿来的 状态呢? 在考虑初学者未接触到 hooksorm

咱们 先从 类 组件来讲。

初始化 state

  1. 首先 咱们新建一个组件 以下 :
import React, { Component } from 'react'
​
export default class App extends Component {
​
  constructor(props) {
    super(props)
    // 初始化状态
    this.state = {
      isHot: true
    }
  }
​
  render() {
    console.log(this)
    return (
      <div>123</div>
    )
  }
}
复制代码

咱们在 类 中 放了一个 构造器 constructor , 调用了 super ( 传递的props 不在本章见作详细说明 咱们先写上 )

  1. 在构造器里 咱们改变了实例对象里面的 state 这时候 咱们启动项目 打开控制台

r3.jpg

能够看见 咱们初始化好了 一个 状态 key : isHot value:true

  1. 读取状态 咱们将 render 方法中的代码改成 以下:
render() {
    console.log(this.state)
    return (
      <h2>今每天气很{this.state.isHot ? '炎热' : '寒冷'}</h2>
    )
  }
​
复制代码

打开页面与控制台 咱们查看一下

r4.jpg

React 中的事件绑定

须要注意的是 原生js 中的 onclick , onblur ... 等等 在 React 中 所有改成 onClick onBlur 这种小驼峰的写法

  1. 接下来 咱们修改 代码以下
import React, { Component } from 'react'
​
export default class App extends Component {
​
  constructor(props) {
    super(props)
    this.state = {
      isHot: true
    }
  }
​
  render() {
    return (
      <h2 onClick={ clickTitle() }>今每天气很{this.state.isHot ? '炎热' : '寒冷'}</h2>
    )
  }
}
​
function clickTitle() {
  console.log('标题被点击了');
}
复制代码
  1. 咱们打开控制台能够看见 咱们尚未点击 , 控制台就已经打印了 。

r5.jpg

咱们能够思考一下为何 ?

onClick = { clickTitle() } 同等于 onClick = { 函数调用的返回值 }

咱们将返回值 直接给到了 onClick 他就自动的去给你点了

咱们将 onClick = { clickTitle() } 后面的调用给去掉 改成 onClick = { clickTitle }

从新回到页面 咱们能够看到 已经能够进行正常的点击操做了

类方法中的 this

此处 咱们接着上一个小节中的内容 继续 。

我须要 点击标题的时候 让炎热变成寒冷 这个时候怎么去处理? 咱们须要将代码修改为 以下:

import React, { Component } from 'react'
​
export default class App extends Component {
​
  constructor(props) {
    super(props)
    this.state = {
      isHot: true
    }
  }
​
  clickTitle() {
    console.log('标题被点击了');
  }
​
  render() {
    return (
      <h2 onClick={ this.clickTitle }>今每天气很{this.state.isHot ? '炎热' : '寒冷'}</h2>
    )
  }
}
复制代码

首先 咱们只须要将 函数从实例的外面 放到实例的里面去

那么 clickTitle 这个方法放在哪儿了呢?

他放在了类的实例对象上,供实例使用

r6.jpg

因此 咱们须要在

<h2 onClick={ this.clickTitle }>今每天气很{this.state.isHot ? '炎热' : '寒冷'}</h2>
复制代码

这句话中 改为 this.clickTitle

启动项目 发现 标题依然是能够被点击的

接下来 咱们将函数内的代码改成

clickTitle() {
    console.log(this.state.isHot);
}
复制代码

这时 控制台就直接报错了

r7.jpg

咱们再去打印 this 时会发现 this 是 undefined

咱们能够知道 constructor 和 render 中的 this 都是指组件的实例对象 ,那么本身定义的clickTitle 里的this为何是undefined呢

r8.jpg

首先咱们要了解到 只有当 clickTitle 这个方法 是组件的实例对象去调用的时候 它里面的 this 才是clickTitle的实例对象

constructor 里的 this 必定是当前实例的 实例对象 是一个固定的东西

注意: 咱们须要知道的是 clickTitle 在调用的时候 并非App这个实例对象去调用他的

这时候 再思考一个问题 既然不是 这个实例去调用他的 那 this 为何是 undefined 不是 window呢 ?

注意:在类中 所定义的方法 它会自动的去在你所定义的方法里面 开启严格模式 开启严格模式后 this 就是 undefined 是 类 自动帮你开启的

解决类中 this 的指向问题

在constructor 里 加一段代码 以下

constructor(props) {
    super(props)
    this.state = {
      isHot: true
    }
   // 解决 this 的指向问题
    this.clickTitle = this.clickTitle.bind(this)
  }
复制代码

这个时候 咱们去控制台 点击标题 查看一下

r9.jpg

this.clickTitle = this.clickTitle.bind(this) 这一段代码 自己是一个赋值语句 咱们在实例对象自己加了一个方法 这个方法从那儿来的呢? 是从原型上来的

r10.jpg

React 中 setState 的使用

此处 咱们接着上一个小节中的内容 继续 。

咱们将函数体的内容改成 以下 :

clickTitle() {
    this.state.isHot = !this.state.isHot
  }
复制代码

运行项目后 发现 点击标题依然不能改变标题的内容

咱们打印 函数里的 this.state.isHot

r11.jpg

会发现 isHot的值确实在改变 可是为何页面不更新呢

严重注意: state( 状态 ) 不可直接更改, this.state.isHot = !this.state.isHot 这一行是错误的写法

此处 咱们须要借助 一个内置的 api 去更改state的值 setState() 。 咱们在函数体内打印 this 能够找到

r12.jpg 在函数体内修改以下代码 :

clickTitle() {
  this.setState({ isHot: !this.state.isHot })
}
复制代码

这时 咱们点击 页面中的 标题 就能够进行切换了

注意: 修改state的值 必须使用 setState 来修改, 且 修改是一个合并的动做 并非直接替换 setState调用几回 render 这个方法就会调用几回 能够本身打印试试

State 的简写方式

将代码改为 以下:

import React, { Component } from 'react'
​
export default class App extends Component {
​
  // constructor(props) {
  //   super(props)
  //   this.state = {
  //   }
  //   this.clickTitle = this.clickTitle.bind(this)
  // }
​
  state = {
    isHot: true
  }
​
  // clickTitle() {
  //   this.setState({ isHot: !this.state.isHot })
  // }
​
  clickTitle = () => {
    this.setState({ isHot: !this.state.isHot })
  }
​
  render() {
    return (
      <h2 onClick={this.clickTitle}>今每天气很{this.state.isHot ? '炎热' : '寒冷'}</h2>
    )
  }
}
复制代码

此处 咱们将 state 从 constructor 直接拿出来

在类中 , 咱们直接写一个赋值的语句 至关于 咱们在 APP 这个实例对象上 新加了一个属性 属性的名字 是 state 它的值是 { isHot:true }

而后 在将 this.clickTitle = this.clickTitle.bind(this) 给注释掉

一样 咱们在实例对象上 新增了一个方法 为 clickTitle 值 是一个 箭头 函数 这样就解决掉了 this 的指向问题 避免在 constructor 频繁的 使用bind 绑定this

将这两行 注释掉了之后 咱们彻底能够将 constructor 这个构造器 给注释掉, 由于咱们没有在里面写任何的内容

如下为完整代码

import React, { Component } from 'react'
​
export default class App extends Component {
  //初始化状态
  state = {
    isHot: true
  }
  //自定义方法 须要采用 赋值语句的形式 + 箭头函数
  clickTitle = () => {
    this.setState({ isHot: !this.state.isHot })
  }
  //渲染
  render() {
    return (
      <h2 onClick={this.clickTitle}>今每天气很{this.state.isHot ? '炎热' : '寒冷'}</h2>
    )
  }
}
复制代码
相关文章
相关标签/搜索