React 3 props 和 state
props
- props只读
- 父子信息传递
子组件只能通过props读取父组件传递的信息,不能改变props.
案例代码:
var WebSite = React.createClass({
render: function() {
return (
<div>
<Name name={this.props.name} />
<Link site={this.props.site} />
</div>
);
}
});
var Name = React.createClass({
render: function() {
return (
<h1>{this.props.name}</h1>
);
}
});
var Link = React.createClass({
//通过 getDefaultProps() 方法为 props 设置默认值
getDefaultProps: function() {
return {
site: 'http://baidu.com'
};
},
render: function() {
return (
<a href={this.props.site}>
{this.props.site}
</a>
);
}
});
ReactDOM.render(
<WebSite name="小仙女儿的博客~" site="http://blog.youkuaiyun.com/zula1994" />,
app
);
上述代码, 为父组件, 和为子组件,ReactDOM.render 时,带了2个参数: name, site, 通过props接收参数并向下传递给和两个子组件。其中,组件通过 getDefaultProps() 方法为 props 设置默认值。如果ReactDOM.render中site值为空或者不传时, 显示的链接应为 http://baidu.com 而不是小仙女儿的博客了~
Props 验证
Props 验证使用 propTypes,它可以保证我们的应用组件被正确使用,React.PropTypes 提供很多验证器 (validator) 来验证传入数据是否有效。当向 props 传入无效数据时,JavaScript 控制台会抛出警告。
常用验证器代码:
React.createClass({ propTypes: { // 可以声明 prop 为指定的 JS 基本数据类型,默认情况,这些数据是可选的 optionalArray: React.PropTypes.array, optionalBool: React.PropTypes.bool, optionalFunc: React.PropTypes.func, optionalNumber: React.PropTypes.number, optionalObject: React.PropTypes.object, optionalString: React.PropTypes.string, // 可以被渲染的对象 numbers, strings, elements 或 array optionalNode: React.PropTypes.node, // React 元素 optionalElement: React.PropTypes.element, // 用 JS 的 instanceof 操作符声明 prop 为类的实例。 optionalMessage: React.PropTypes.instanceOf(Message), // 用 enum 来限制 prop 只接受指定的值。 optionalEnum: React.PropTypes.oneOf(['News', 'Photos']), // 可以是多个对象类型中的一个 optionalUnion: React.PropTypes.oneOfType([ React.PropTypes.string, React.PropTypes.number, React.PropTypes.instanceOf(Message) ]), // 指定类型组成的数组 optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number), // 指定类型的属性构成的对象 optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number), // 特定 shape 参数的对象 optionalObjectWithShape: React.PropTypes.shape({ color: React.PropTypes.string, fontSize: React.PropTypes.number }), // 任意类型加上 `isRequired` 来使 prop 不可空。 requiredFunc: React.PropTypes.func.isRequired, // 不可空的任意类型 requiredAny: React.PropTypes.any.isRequired, // 自定义验证器。如果验证失败需要返回一个 Error 对象。不要直接使用 `console.warn` 或抛异常,因为这样 `oneOfType` 会失效。 customProp: function(props, propName, componentName) { if (!/matchme/.test(props[propName])) { return new Error('Validation failed!'); } } }, /* ... */ });
state
state是React中组件的一个对象.React把用户界面当做是状态机,想象它有不同的状态然后渲染这些状态,可以轻松让用户界面与数据保持一致.
React中,更新组件的state,会导致重新渲染用户界面(不要操作DOM).简单来说,就是用户界面会随着state变化而变化.
下面用一个简单的案例介绍一下state。
import React from 'react';
import ReactDOM from 'react-dom';
class SwitchButton extends React.Component {
constructor(props) {
super(props)
this.state = {
open: this.props.open
}
}
handleClick() {
this.setState({open: !this.state.open})
}
render() {
return (
<label onClick={this.handleClick.bind(this)}><input type="checkbox" checked = {this.state.open || false} />{this.state.open ? '开启':'关闭'}</label>
);
}
};
SwitchButton.defaultProps = {
open: false
}
export default SwitchButton;
咳咳。。还是用之前的那个SwitchButton的例子介绍吧,绝对不是我偷懒!!!= ̄ω ̄=
上面 SwitchButton 组件通过构造函数方式创建,在 constructor 方法里通过super继承props参数。 通过this.state设置初始状态值。
在 handleClick 方法里通过 this.setState 设置state。每次设置state后都会调用render方法重新渲染组件。
正确使用状态
使用
this.setState({comment: 'Hello'})
而不是this.state.comment = 'Hello';
构造函数是唯一能够初始化 this.state 的地方。
状态更新可能是异步的
... constructor(props) { super(props) this.state = { comment: 'Hi' } } ... this.setState({comment: 'Hello'}) console.log(this.state) //Hi ...
因为this.setState可能是异步的,所以设置状态后打印state时会显示更新前的状态值,如果需要立即使用更新后的状态,需要在setState的回调函数里使用
this.setState({comment: 'Hello'}, () => {console.log(this.state) // Hello})
- 数据自顶向下流动,单向传递