复盘React 三大核心属性之state
目标:如图,点击文本修改数据
点击前:
点击后
state
state是react实例身上的三大属性之一,我们在constructor构造函数内打印this,可以看到实例身上确实默认设置了这么一个属性:
打印结果
因为我们是在继承的情况下,在实例中重写了构造函数,所以首先要调用一下super,另外我们可以初始化这个默认的state,如图:
这样一来,在控制台内,就可以看到我们为state设置的值
接着我们可以在render函数里设置文本结构,以及将state对象中的属性解构出来
可以看到我们给h1标签加了一个changeWeather的点击事件,并在文本区域做了判断来影响最终的效果
接着我就来定义这个方法,如下
可以看到我们把实例身上的state对象中的isHot拿出来了,接着由于我们的目标是点击文本切换关键词,所以要利用this.setState这个方法,其内部接收一个对象,并且给isHot取反,这样一来,就可以正常切换文本了
注意:不要直接修改state里的值!例如this.state.xxx=yyy,这样是错误的。要利用this.setState这个方法来进行修改
然后我们来点击文本查看效果
我们惊讶的发现居然报错,这是为什么呢?原来在类的内部,方法默认开启了严格模式,也就是说我们自定义的方法默认是指向undefined,因此这个undefined身上完全没有setState这个方法。那要怎么办呢?
这时候我们可以给这个方法调用bind方法,强制让这个方法的this指向这个缔造出来的实例,如图:
这里梳理一下,实例的原型对象上是有我们设置的自定义方法changeWeather的,bind方法的作用就是改变函数内部this指向,以及调用函数返回一个新函数,这样一来这个自定义方法内部的this就指向实例本身了。等号左边我们又给这个实例身上加了一个changeWeather方法,接着我们来打印看一下这个实例
可以看到添加成功
最后一步,调用ReactDOM.render方法将这个类式组件渲染到页面上
这时候点击页面文本,就可以正常切换了
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>state</title>
</head>
<body>
<!-- 准备好一个“容器” -->
<div id="test"></div>
<!-- 引入react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作DOM -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
//1.创建组件
class Weather extends React.Component{
//构造器调用几次? ———— 1次
constructor(props){
console.log('constructor');
super(props)
//初始化状态
this.state = {isHot:false,wind:'微风'}
//解决changeWeather中this指向问题
this.changeWeather = this.changeWeather.bind(this)
}
//render调用几次? ———— 1+n次 1是初始化的那次 n是状态更新的次数
render(){
console.log('render');
//读取状态
const {isHot,wind} = this.state
return <h1 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'},{wind}</h1>
}
//changeWeather调用几次? ———— 点几次调几次
changeWeather(){
//changeWeather放在哪里? ———— Weather的原型对象上,供实例使用
//由于changeWeather是作为onClick的回调,所以不是通过实例调用的,是直接调用
//类中的方法默认开启了局部的严格模式,所以changeWeather中的this为undefined
console.log('changeWeather');
//获取原来的isHot值
const isHot = this.state.isHot
//严重注意:状态必须通过setState进行更新,且更新是一种合并,不是替换。
this.setState({isHot:!isHot})
console.log(this);
//严重注意:状态(state)不可直接更改,下面这行就是直接更改!!!
//this.state.isHot = !isHot //这是错误的写法
}
}
//2.渲染组件到页面
ReactDOM.render(<Weather/>,document.getElementById('test'))
</script>
</body>
</html>