首先 咱们用最通俗易懂的话来理解, 好比 每一个人都有本身的状态 , 每一个人的状态 都会影响 他的行为,react
那么, 咱们将这句话放到 react 中去理解,把人看做是 组件,组件也有本身的状态,组件的状态会影响api
它的页面。markdown
咱们在游览各大网页时,会发现 网页上有一些数据,如我的信息 帐号 以及一些新闻列表等等。 这些都app
是数据, 咱们将这些数据放在了页面上,那么是什么驱动着页面的改变呢? 是数据。 这时候咱们只须要函数
将数据 放入状态 ( state ) 中 ,咱们去更改状态 页面也会随之变化。this
import React, { Component } from 'react'
export default class App extends Component {
render() {
console.log(this)
return (
<div>
app组件
</div>
)
}
}
复制代码
如今咱们回到 第一个问题 理解什么是 state ?spa
1 . state 是组件对象最重要的属性 ,值是对象 ( 里面能够包含多个 key : value 的 组合 ) 虽然在初始化看到的是null , 在react以前的版本中 仍是一个 { }3d
2 . 组件被称之为状态机 , 经过更新组件里的 state 来更新对应的页面显示 ( 从新渲染组件 )code
须要注意的地方 : 因有函数时组件与类式组件 react 将状态放到了 实例对象里 函数时组件 连this都没有 哪儿来的 状态呢? 在考虑初学者未接触到 hooksorm
咱们 先从 类 组件来讲。
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 不在本章见作详细说明 咱们先写上 )
能够看见 咱们初始化好了 一个 状态 key : isHot value:true
render() {
console.log(this.state)
return (
<h2>今每天气很{this.state.isHot ? '炎热' : '寒冷'}</h2>
)
}
复制代码
打开页面与控制台 咱们查看一下
须要注意的是 原生js 中的 onclick , onblur ... 等等 在 React 中 所有改成 onClick onBlur 这种小驼峰的写法
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('标题被点击了');
}
复制代码
咱们能够思考一下为何 ?
onClick = { clickTitle() } 同等于 onClick = { 函数调用的返回值 }
咱们将返回值 直接给到了 onClick 他就自动的去给你点了
咱们将 onClick = { clickTitle() } 后面的调用给去掉 改成 onClick = { clickTitle }
从新回到页面 咱们能够看到 已经能够进行正常的点击操做了
此处 咱们接着上一个小节中的内容 继续 。
我须要 点击标题的时候 让炎热变成寒冷 这个时候怎么去处理? 咱们须要将代码修改为 以下:
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 这个方法放在哪儿了呢?
他放在了类的实例对象上,供实例使用
因此 咱们须要在
<h2 onClick={ this.clickTitle }>今每天气很{this.state.isHot ? '炎热' : '寒冷'}</h2>
复制代码
这句话中 改为 this.clickTitle
启动项目 发现 标题依然是能够被点击的
接下来 咱们将函数内的代码改成
clickTitle() {
console.log(this.state.isHot);
}
复制代码
这时 控制台就直接报错了
咱们再去打印 this 时会发现 this 是 undefined
咱们能够知道 constructor 和 render 中的 this 都是指组件的实例对象 ,那么本身定义的clickTitle 里的this为何是undefined呢
首先咱们要了解到 只有当 clickTitle 这个方法 是组件的实例对象去调用的时候 它里面的 this 才是clickTitle的实例对象
constructor 里的 this 必定是当前实例的 实例对象 是一个固定的东西
注意: 咱们须要知道的是 clickTitle 在调用的时候 并非App这个实例对象去调用他的
这时候 再思考一个问题 既然不是 这个实例去调用他的 那 this 为何是 undefined 不是 window呢 ?
注意:在类中 所定义的方法 它会自动的去在你所定义的方法里面 开启严格模式 开启严格模式后 this 就是 undefined 是 类 自动帮你开启的
在constructor 里 加一段代码 以下
constructor(props) {
super(props)
this.state = {
isHot: true
}
// 解决 this 的指向问题
this.clickTitle = this.clickTitle.bind(this)
}
复制代码
这个时候 咱们去控制台 点击标题 查看一下
this.clickTitle = this.clickTitle.bind(this) 这一段代码 自己是一个赋值语句 咱们在实例对象自己加了一个方法 这个方法从那儿来的呢? 是从原型上来的
此处 咱们接着上一个小节中的内容 继续 。
咱们将函数体的内容改成 以下 :
clickTitle() {
this.state.isHot = !this.state.isHot
}
复制代码
运行项目后 发现 点击标题依然不能改变标题的内容
咱们打印 函数里的 this.state.isHot
会发现 isHot的值确实在改变 可是为何页面不更新呢
严重注意: state( 状态 ) 不可直接更改, this.state.isHot = !this.state.isHot 这一行是错误的写法
此处 咱们须要借助 一个内置的 api 去更改state的值 setState() 。 咱们在函数体内打印 this 能够找到
在函数体内修改以下代码 :
clickTitle() {
this.setState({ isHot: !this.state.isHot })
}
复制代码
这时 咱们点击 页面中的 标题 就能够进行切换了
注意: 修改state的值 必须使用 setState 来修改, 且 修改是一个合并的动做 并非直接替换 setState调用几回 render 这个方法就会调用几回 能够本身打印试试
将代码改为 以下:
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>
)
}
}
复制代码