react中的this.props_this.state详解

以下分享来自团队童鞋yangjun

  • React是单向数据流,数据主要从父节点通过props传递到子节点。
  • 如果顶层(父级)的某个props改变了,React会重渲染所有的子节点。
  • 通常使用props当做数据源,state用来存放状态值(简单的数据)。
  • 通常用props传递大量数据,state用于存放组件内部一些简单的定义数据。 ###this.props
    props是只读的,props用于整个组件树中传递数据和配置。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var MessagesBox = React.createClass({
    getDefaultProps:function(){
    return {title:"我也是死的,没有title传递过来时,我是默认值,读取我!"}
    },
    render:function(){
    return (
    <div>{this.props.title}</div>
    )
    }
    })
    var title="我是死的,用于props传递!"
    React.render(<MessagesBox title={title} />,document.getElementById('app'));

(其中title为外部定义的变量,由父组件传递到子组件,由props进行数据的传递即this.props.title获取数据,当父组件没有向子组件传值时可设置getDefaultProps返回值并进行读取)

#####props中Proptypes验证
在开发时使用Proptypes用于验证props传递数据的有效性,数据类型错误时控制台会提示警告(不会报错,也不会阻止代码的后续执行)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
var Propsva = React.createClass({
propTypes: {
optionalArray:React.PropTypes.array,
optionalBool:React.PropTypes.bool,
optionalFunc:React.PropTypes.func,
optionalNumber:React.PropTypes.number,
optionalObject:React.PropTypes.object,
optionalString:React.PropTypes.string,
},
getDefaultProps:function(){
return {
optionalArray:["我是A","我是B"],
optionalBool:true,
optionalFunc:function(arg){
console.log(arg);
},
optionalNumber:100,
optionalObject:{
object1:"objectvalue1",
object2:"objectvalue2",
object3:"objectvalue3",
},
optionalString:"我的组件",
};
},
render:function(){
return (
<div>
<h2>{this.props.optionalArray}</h2>
<h2>{this.props.optionalBool}</h2>
<h2>{this.props.optionalNumber}</h2>
<h2>{this.props.optionalObject}</h2>
<h2>{this.props.optionalString}</h2>
<h2>{this.props.optionalFunc("123")}</h2>
</div>
)
}
})
React.render(<Propsva/>,document.getElementById("app"));

###this.state
每个组件都有属于自己的state,state和props的区别在于前者(state)只存在于组件内部,只能从当前组件调用this.setState修改state值(不可以直接修改this.state!)。

注:一般我们更新子组件都是通过改变state值,更新子组件的props值从而达到更新。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
var MessageBox = React.createClass({
getInitialState:function(){
return { num:1 }
},
handleClick:function(){
this.setState(function(state){
state.num=this.state.num*2
})
},
render:function(){
return (
<div>
<button onClick={this.handleClick}>点我改变子组件的值</button>
<Submessage messages={this.state.num}/>
</div>
)
}
});
var Submessage = React.createClass({
render:function(){
console.log("渲染")
return (
<div>
<div>点击按钮num×2</div>
<input type="text" value={this.props.messages}/>
</div>
)
}
});
var messageBox = React.render( <MessageBox/>, document.getElementById('app'))

这里使用getIniatialState定义一个状态,并通过点击事件改变状态,将改变后的num值通过this.props传递给子组件,当状态改变时,子组件会随着更新并重新渲染

####组件之间进行沟通

  • 父子组件沟通
    通常情况下都是父子组件进行数据沟通
    1、父组件通过props更新子组件,向上边写的那样
      父组件 → props → 子组件
    2、子组件通过回调函数更新父组件状态
     子组件 → 父组件的回调函数 → 子组件调用触发
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    var Son=React.createClass({
    render:function(){
    return (
    <button onClick={this.props.refreshParent}>点击我更新父组件</button>
    )
    }
    })
    var Parent = React.createClass({
    getInitialState:function(){
    return {index:0}
    },
    refreshParent:function(){
    var self=this;
    this.setState(function(state){
    state.index=self.state.index+1
    })
    },
    render:function(){
    return (
    <div>
    我是父组件的第{this.state.index}个数值
    <Son refreshParent={this.refreshParent}></Son>
    </div>
    )
    }
    })
    React.render(<Parent/>,document.getElementById('app'));

父组件Parent中定义了index状态,并定义了refreshParent方法用于改变index的值,通过props将refreshParent方法传递到子组件,并在子组件中触发执行

  • 兄弟组件沟通
     1、按照React单向数据流方式,我们需要借助父组件进行传递,通过父组件回调函数改变兄弟组件的props。其实这种实现方式与子组件更新父组件状态的方式是大同小异的。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    var Brother1 = React.createClass({
    render:function(){
    return (
    <div>
    <button onClick={this.props.refresh}>点我时我兄弟收到消息</button>
    </div>
    )
    }
    })
    var Brother2 = React.createClass({
    render:function(){
    return (
    <div>{this.props.text}</div>
    )
    }
    })
    var Parent = React.createClass({
    getInitialState:function(){
    return {text:"我是brother2"}
    },
    refresh:function(){
    this.setState({
    text:"收到收到!!!"
    })
    },
    render:function(){
    return (
    <div>
    <h1>兄弟组件更新</h1>
    <Brother1 refresh={this.refresh}/>
    <Brother2 text={this.state.text}/>
    </div>
    )
    }
    })
    React.render(<Parent/>,document.getElementById("app"));

 2、当组件中的层级很深时,可使用context跨组件传递数据(但使用过多会造成数据传递混乱)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
var A = React.createClass({
getInitialState:function(){
return { index:1 }
},
childContextTypes: {
clickFunc:React.PropTypes.func,
index:React.PropTypes.number,
},
getChildContext: function() {
return {
clickFunc:this.handleClick,
index:this.state.index,
};
},
handleClick:function(){
this.setState({
index:this.state.index*3
})
},
render: function() {
return (<B />);
}
});
var B = React.createClass({
contextTypes: {
clickFunc:React.PropTypes.func,
index:React.PropTypes.number,
},
render: function() {
console.log(this.context) //打印出来{clickFunc:handleClick,index:1}
return <div onClick={this.context.clickFunc}>点击我啊{this.context.index}</div>;
}
});
React.render(<A />,document.getElementById('app'));

#####shouldComponentUpdate,componentWillReceiveProps

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
componentWillReceiveProps:function(nextProp,nextState){
console.log(nextProp,nextState+"=====1")
console.log(this.props,this.state+"=====2")
console.log('子组件将要获得prop');
this.setState({
count:nextProp.count
},function(){
console.log(this.state.count)
})
},
shouldComponentUpdate:function(nextProp,nextState){
console.log(nextProp,nextState+"=====3")
console.log(this.props,this.state+"=====4")
if(nextProp.count> 5) return false;
return true;
},

shouldComponentUpdate方法是react内置的方法,用于控制是否更新,有一个返回值,若为true,则更新,否则,不更新;方法中,nextProps为props改变后的值,而this.props为nextProps的前一个值。

componentWillReceiveProps当props有变动时,在组件更新前,componentWillReceiveProps会优于shouldComponentUpdate执行