我们都说React是一个状态机,体现是什么地方呢,就是体现在state上,通过与用户的交互,实现不同的状态,然后去渲染UI,这样就让用户的数据和界面保持一致了。state是组件的私有属性。
在React中,更新组件的state,结果就会重新渲染用户界面(不需要操作DOM),一句话就是说,用户的界面会随着状态的改变而改变。
state是组件对象最重要的属性,值是对象(可以包含多个key-value的组合)
案例:
1.需求:页面显示【今天天气很炎热】,鼠标点击文字的时候,页面更改为【今天天气很凉爽】
核心代码如下:
需要注意的是:
组件的构造函数,必须要传递一个props参数
特别关注this【重点】,类中所有的方法局部都开启了严格模式,如果直接进行调用,this就是undefined
想要改变state,需要使用setState进行修改,如果只是修改state的部分属性,则不会影响其他的属性,这个只是合并并不是覆盖。
this.setState(),该方法接收两种参数:对象或函数。
在此还需要注意的是,setState有异步更新和同步更新两种形式,那么什么时候会同步更新,什么时候会异步更新呢?
React控制之外的事件中调用setState是同步更新的。比如原生js绑定的事件,setTimeout/setInterval等。
大部分开发中用到的都是React封装的事件,比如onChange、onClick、onTouchMove等,这些事件处理程序中的setState都是异步处理的。
//1.创建组件
class St extends React.Component{
//可以直接对其进行赋值
state = {isHot:10};
render(){ //这个This也是实例对象
return 点击事件
}
//箭头函数 [自定义方法--->要用赋值语句的形式+箭头函数]
dem = () =>{
//修改isHot
this.setState({ isHot: this.state.isHot + 1})
console.log(this.state.isHot);
}
}
上面的案例中预期setState使得isHot变成了11,输出也应该是11。然而在控制台打印的却是10,也就是并没有对其进行更新。这是因为异步的进行了处理,在输出的时候还没有对其进行处理。
componentDidMount(){
document.getElementById("test").addEventListener("click",()=>{
this.setState({isHot: this.state.isHot + 1});
console.log(this.state.isHot);
})
}
但是通过这个原生JS的,可以发现,控制台打印的就是11,也就是已经对其进行了处理。也就是进行了同步的更新。
React怎么调用同步或者异步的呢?
在 React 的 setState 函数实现中,会根据一个变量 isBatchingUpdates 判断是直接更新 this.state 还是放到队列中延时更新,而 isBatchingUpdates 默认是 false,表示 setState 会同步更新 this.state;但是,有一个函数 batchedUpdates,该函数会把 isBatchingUpdates 修改为 true,而当 React 在调用事件处理函数之前就会先调用这个 batchedUpdates将isBatchingUpdates修改为true,这样由 React 控制的事件处理过程 setState 不会同步更新 this.state。
如果是同步更新,每一个setState对调用一个render,并且如果多次调用setState会以最后调用的为准,前面的将会作废;如果是异步更新,多个setSate会统一调用一次render
dem = () =>{
this.setState({
isHot: 1,
cont:444
})
this.setState({
isHot: this.state.isHot + 1
})
this.setState({
isHot: 888,
cont:888
})
}
上面的最后会输出:isHot是888,cont是888
dem = () =>{
this.setState({
isHot: this.state.isHot + 1,
})
this.setState({
isHot: this.state.isHot + 1,
})
this.setState({
isHot: this.state.isHot + 888
})
}
初始isHot为10,最后isHot输出为898,也就是前面两个都没有执行。
**注意!!这是异步更新才有的,如果同步更新,每一次都会调用render,这样每一次更新都会 **
简化版本:
state的赋值可以不再构造函数中进行
使用了箭头函数,将this进行了改变
如果想要在调用方法的时候传递参数,有两个方法:
上述两种方式是等价的,分别通过箭头函数和 Function.prototype.bind
来实现。
在这两种情况下,React 的事件对象 e
会被作为第二个参数传递。如果通过箭头函数的方式,事件对象必须显式的进行传递,而通过 bind
的方式,事件对象以及更多的参数将会被隐式的进行传递。
Props主要用来传递数据,比如组件之间进行传值
基本使用:
如果传递的数据是一个对象,可以更加简便的使用
… 这个符号恐怕都不陌生,这个是一个展开运算符,主要用来展开数组,如下面这个例子:
arr = [1,2,3];
arr1 = [4,5,6];
arr2 = [...arr,...arr1]; //arr2 = [1,2,,3,4,5,6]
但是他还有其他的用法:
1.复制一个对象给另一个对象{…对象名}。此时这两个对象并没有什么联系了
const p1 = {name:"张三",age:"18",sex:"女"}
const p2 = {...p1};
p1.name = "sss";
console.log(p2) //{name:"张三",age:"18",sex:"女"}
2.在复制的时候,合并其中的属性
const p1 = {name:"张三",age:"18",sex:"女"}
const p2 = {...p1,name : "111",hua:"ss"};
p1.name = "sss";
console.log(p2) //{name: "111", age: "18", sex: "女",hua:"ss"}
注意!! {…P}并不能展开一个对象
props传递一个对象,是因为babel+react使得{…p}可以展开对象,但是只有在标签中才能使用
对于props限制
很多时候都想要传递的参数进行相应的限制,比如:限制传递参数的类型,参数的默认值等等
react对此提供了相应的解决方法: