复盘React 三大核心属性(state, props, refs)

135 阅读2分钟

复盘React 三大核心属性之state

目标:如图,点击文本修改数据

点击前:

image.png

点击后

image.png

state

state是react实例身上的三大属性之一,我们在constructor构造函数内打印this,可以看到实例身上确实默认设置了这么一个属性:

image.png

打印结果

image.png

因为我们是在继承的情况下,在实例中重写了构造函数,所以首先要调用一下super,另外我们可以初始化这个默认的state,如图:

image.png

这样一来,在控制台内,就可以看到我们为state设置的值

image.png

接着我们可以在render函数里设置文本结构,以及将state对象中的属性解构出来

image.png

可以看到我们给h1标签加了一个changeWeather的点击事件,并在文本区域做了判断来影响最终的效果

接着我就来定义这个方法,如下

image.png

可以看到我们把实例身上的state对象中的isHot拿出来了,接着由于我们的目标是点击文本切换关键词,所以要利用this.setState这个方法,其内部接收一个对象,并且给isHot取反,这样一来,就可以正常切换文本了

注意:不要直接修改state里的值!例如this.state.xxx=yyy,这样是错误的。要利用this.setState这个方法来进行修改

然后我们来点击文本查看效果

image.png

我们惊讶的发现居然报错,这是为什么呢?原来在类的内部,方法默认开启了严格模式,也就是说我们自定义的方法默认是指向undefined,因此这个undefined身上完全没有setState这个方法。那要怎么办呢?

这时候我们可以给这个方法调用bind方法,强制让这个方法的this指向这个缔造出来的实例,如图:

image.png

这里梳理一下,实例的原型对象上是有我们设置的自定义方法changeWeather的,bind方法的作用就是改变函数内部this指向,以及调用函数返回一个新函数,这样一来这个自定义方法内部的this就指向实例本身了。等号左边我们又给这个实例身上加了一个changeWeather方法,接着我们来打印看一下这个实例

image.png

可以看到添加成功

最后一步,调用ReactDOM.render方法将这个类式组件渲染到页面上

image.png

这时候点击页面文本,就可以正常切换了

image.png

代码

<!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>