1、react的组件存放数据有两种方式。
(1)、存放外部数据的props,数据是只读,是不能修改的。
(2)、存放组件内部数据的state,存放组件自己的数据,其是放到constructor(){}里面。
2、关于constructor。
(1)constructor是先于render执行的
(2)constructor是什么时候调用?new的时候。new的时候做四件事:①新产生一个对象②让this指向新产生的对象③执行这个函数④会返回这个新创建的对象。
3、constructor里面的this
(1)在constructor里面直接输出this是不行的,会报错。
错误:this不被允许出现在super()之前。
(2)所以要用this得先写super()。
this是指向当前的实例,super是指向父类的实例,但是super()是调用父类的构造函数。
它是先实例化父类的实例 再实例化自己,不写super()得不到this。
但是以下写法可以得到this,但是得不到props。
constructor(){ //构造函数
super();
console.log(this.props)
}
要得到props可以在super()里面写super(props)
constructor(props){ //构造函数
super(props);
console.log(this.props)
console.log(props); //super里写了props后可以省去this
}
4、state用法
(1)写法
constructor(props){
super(props);
this.state = { //存放组件本身的数据
n:1,
visible:true,
arr:[1,2,3]
}
}
(2)修改state里面的值
①直接修改this.state.visible,这个方式会导致 数据会变,但是视图不会同步变,尽量避免用这种方式。
class Group extends React.Component {
constructor(props){
super(props);
this.state = { //存放组件本身的数据
n:1,
visible:true,
arr:[1,2,3]
}
this.toggle = this.toggle.bind(this); //toggle 能访问到this
}
toggle(){
this.state.visible = !this.state.visible
console.log(this.state.visible)
})
}
render(){
return <div>{this.state.visible}</div>
}
}
解决方法:在toggle里面加一句this.forceUpdate()
。但这种方式很不优雅,不推荐,最好永远不要用这种方式。
②使用setState({})
语法,会改变state里面的值,触发render。
<div id="box"></div>
<script type="text/babel">
class Demo extends React.Component { //类组件 有state
constructor(props){
super(props);
this.state = {
n:1
}
this.increment = this.increment.bind(this);
}
increment(){
this.setState({ //异步的
n:this.state.n+1
},()=>{
console.log(this.state.n)
})
}
render(){
return <div> {this.state.n}
<button onClick={this.increment}>+1</button>
</div>
}
}
var App = () =>{ //无状态组件
return <div>
<Demo />
</div>
}
ReactDOM.render(<App />,document.querySelector("#box"));
</script>
但是!!!
缺点:每次setState都会触发render,所以如果写两次setState按理说会有两次render,这个时候react不干了,因为每次都渲染效果效率会非常差劲。所以!它会把你两次的setState合并了!后面的会覆盖前面的,所以它只会执行最后一个操作。
不信可以执行下面的例子:
increment(){
this.setState({ //异步的
n:this.state.n+1
},()=>{
console.log(this.state.n)
})
this.setState({ //异步的
// n:this.state.n+5
},()=>{
console.log(this.state.n)
})
}
为了解决要连续使用setState的问题,③方法诞生了。
③使用this.setState((prevState,props)=>{return {} })
语法
increment(){
this.setState((prevState,props)=>{
return {
n:prevState.n+1
}
})
this.setState((prevState,props)=>{
return {
n:prevState.n+1
}
})
}
此方法两个setState都会执行。因为这个setState()里面放的不是对象,而是函数。对象相同就会合并,但是函数是不会合并的,它们都会放到队列里面去依次执行。