1.state
state应该称为
内部状态或局部状态,react组件可以在构造函数中初始化内部状态,可以通过this.setState方法更新内部状态,还可以使用this.state获取内部状态,内部状态的操作与react事件系统配合可以实现用户交互的功能。
import React, { Component } from 'react';
//content组件
function Content(props){
return <p>props.value: {props.value}</p>
}
class App extends Component {
//在构造函数中初始化内部状态,构造函数仅在实例化一个类的时候被调用
constructor(){
//子类的构造函数中,必须先调用super(),才能使用this获取实例化对象
super();
this.state = {value : 0};
}
render() {
return (
<div className="App">
//内部状态state和事件,点击button更改value的状态
<button onClick = {() => this.setState({value : this.state.value + 1})}>按下</button>
<pre>{this.state.value}</pre>
//props
<Content value={this.state.value} />
</div>
);
}
}
export default App;
2.props
使用props向react组件传递数据,react组件从props中拿到数据,然后返回视图(逐层传递)。
使用props:
将数据写在组件标签的属性中,在无状态函数编写的组件中获取props只需要将props作为参数传入组件,在使用类编写的组件中,需要通过this.props获取props。
验证props:
验证props需要使用
React.propTypes,它提供很多验证器来验证传入数据是否合法,
当向props传入非法数据时,控制台会抛出警告。
Content.propTypes = {
value : PropTypes.number
}
验证器:
- javascript基本数据类型:React.PropTypes.array/bool/func/number/object/string
- 可以被渲染为子节点的对象:React.PropTypes.node
- ReactElement(JSX中的闭合标签):React.PropTypes.element
- 指定类的实例:React.PropTypes.instanceOf(Message)
- 只接受指定的值:React.PropTypes.oneOf([ ' News ' , ' Photos ' ])
- 多个对象类型中的一个:
React.PropTypes.oneOfType([
React.PropTypes.string,
React.PropTypes.number,
React.PropTypes.instanceOf(Message)
])
- 指定类型组成的数组:React.PropTypes.arrayOf(React.PropTypes.number)
- 指定类型的属性构成的对象:React.PropTypes.objectOf(React.PropTypes.number)
- 符合指定格式的对象:
React.PropTypes.shape({
color : React.PropTypes.string,
fontSize : React.PropTypes.number
})
- 任意类型加上isRequired使其不可为空:React.PropTypes.func.isRequired
- 自定义验证器
function(props, propName, componentName){
if(!/matchme/.test(props[propName])){
return new Error('validation failed');
}
}
例子:三层组件props传递数据
function Button(props){
return (
//3.最终传递到最底层组件
<button style={{background: props.color}}>{props.children}</button>
)
}
function Message(props){
return(
//2.子组件接收,并将color继续传递给下一层子组件
<li>{props.text}<Button color={props.color}>Delete</Button></li>
)
}
function MessageList(){
const color = 'gray';
const messages = [
{text: 'hello react'},
{text: 'hello redux'}
];
const children = messages.map((message, key) => {
<div>
//1.通过标签的属性传递props,传递了key、text、color
<Message key={key} text={message.text} color={color}/>
</div>
})
return(
<div>
<ul>
{children}
</ul>
</div>
)
}
3.context
context可以跨级传递数据。
步骤:
- 将要传的数据放在数据源组件的context中
- 在需要数据的组件中声明contextTypes
//4.传递父组件的props和全局的context
function Button(props,context){
return (
//获取context,如果是无状态组件则直接获取context,有状态则通过this,context和生命周期函数
<button style={{background: context.color}}>{props.children}</button>
)
}
//3.定义contextTypes,不定义则是个空对象
Button.contextTypes = {
color:PropTypes.string.isRequired
}
function Message(props){
return(
<li>{props.text}<Button>Delete</Button></li>
)
}
class MessageList extends Component {
//2.将color放在context中
getChildContext(){
return {color:'gray'}
}
render(){
const messages = [
{text: 'hello react'},
{text: 'hello redux'}
];
const children = messages.map((message, key) =>
<div>
<Message key={key} text={message.text}/>
</div>
)
return(
<div>
<ul>
{children}
</ul>
</div>
)
}
}
//1.声明childContextTypes,不声明则无法在组件中使用getChildContext方法
MessageList.childContextTypes = {
color: PropTypes.string.isRequired
}
4.适用场景
props:传递一些功能模块的数据
context:传递登陆信息、当前语言、主题信息等