本文仅作为个人学习React的笔记,文中省略了基础的知识点和术语。在阅读本文前,默认已经准备好了React的运行环境。
本文重点记录React的组件部分,且不使用ES6的特性。
如何创建一个组件?
创建一个组件使用React.createClass(object)
方法,作为组件,该方法返回的变量名称必须以大写字母开头。
示例:
var HelloMessage = React.createClass({
render: function() {
return <h1>Hello Message!</h1>;
}
});
在React.createClass参数必须是一个JS对象,其必须实现一个名为render方法,该方法的返回值是一个只包含一个根节点的Dom对象(可以包含自定义组件)。
组件的属性 props
组件的属性可以使用this.props
来获取,该属性值来源于组件调用时的定义,属性在定义后就不能被修改,除非重新生成组件。
属性定义示例:
ReactDOM.render(
<HelloMessage name="zsea.Message" />,
document.getElementById('example')
);
其中,组件包含名称为name属性,可以能过this.props.name
来获取。
特殊属性:props.children
该属性为组件的子对象,若子对象只有一个,该值为一个JS对象,若有多个,则为JS数组。当为JS数组时,呈现的子对象必须包含key
属性。
为了简化操作,React提供了方法React.Children.map(children,function(){})
用于遍历子对象,使用该方法遍历时,不需要区分是JS数组还是JS对象。
示例:
var NotesList = React.createClass({
render: function() {
return (
<ol>
{
React.Children.map(this.props.children, function (child,_index) {
return <li key={_index}>{child}</li>;
})
}
</ol>
);
}
});
ReactDOM.render(
<NotesList>
<span>hello</span>
<span>world</span>
</NotesList>,
document.body
);
属性验证 PropTypes
为保证组件被正确使用,React引入了
propTypes
,用于对属性进行校验,同时,React.PropTypes
提供了大量的验证器来验证传入数据的有效性。当向 props 传入无效数据时,JavaScript 控制台会抛出警告。为了性能考虑,建议只在开发环境验证 propTypes。
下面用例子来说明不同验证器的区别:
React.createClass({
propTypes: {
// 可以声明 prop 为指定的 JS 基本类型。默认
// 情况下,这些 prop 都是可传可不传的。
optionalArray: React.PropTypes.array,
optionalBool: React.PropTypes.bool,
optionalFunc: React.PropTypes.func,
optionalNumber: React.PropTypes.number,
optionalObject: React.PropTypes.object,
optionalString: React.PropTypes.string,
optionalSymbol: React.PropTypes.symbol,
// 所有可以被渲染的对象:数字,
// 字符串,DOM 元素或包含这些类型的数组(or fragment) 。
optionalNode: React.PropTypes.node,
// React 元素
optionalElement: React.PropTypes.element,
// 你同样可以断言一个 prop 是一个类的实例。
// 用 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),
// 特定形状参数的对象
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!');
}
}
},
/* ... */
});
React也提供了针对子对象的验证器
用
React.PropTypes.element
你可以指定仅有一个子级能被传送给组件。
var MyComponent = React.createClass({
propTypes: {
children: React.PropTypes.element.isRequired
},
render: function() {
return (
<div>
{this.props.children} // 这里必须是一个元素否则就会警告
</div>
);
}
});
默认属性 getDefaultProps
当父级没有传入 props 时,getDefaultProps()
可以保证 this.props.value
有默认值,注意 getDefaultProps 的结果会被缓存。得益于此,你可以直接使用 props,而不必写手动编写一些重复或无意义的代码。
该接口要求返回一个JS对象。
示例:
var ComponentWithDefaultProps = React.createClass({
getDefaultProps: function() {
return {
value: 'default value'
};
}
});
组件的状态 state
组件的属性在被定义后,是不允放被修改的。但是,React同时也提供了组件的状态,状态是允许被在内部修改的。
获取组件状态使用this.state
,this.state
是一个JS对象。
示例:
var HelloMessage = React.createClass({
render: function() {
return <h1>Hello Message {this.state.time}!</h1>;
}
});
其中,time为组件的一个状态。
状态的修改 setState
在语言层面,我们可以直接使用'='来修改组件的状态(this.state),但是,这种方法的修改并不能使组件触发render,修改后的状态并不能反映在WEB界面上。
Reace为我们提供了统一的状态修改方法:this.setState(state)
,参数state是一个JS对象,其中只需要标识需要被修改的对象,而this.state中已经存在的非同名对象不会被覆盖。该方法仅能在组件内部调用。
初始状态 getInitialState
状态是由组件内部进行控制,在没有任何方法调用前,React提供了一个接口用于组件状态的初始化:getInitialState
,该接口要求返回一个JS对象。
示例:
var HelloMessage = React.createClass({
getInitialState:function(){
return {time:'2016-12-23'};
},
render: function() {
return <h1>Hello Message {this.state.time}!</h1>;
}
});
在getInitialState接口中,可以使用组件的属性值做为组件的状态。
示例:
var HelloMessage = React.createClass({
getInitialState:function(){
return {time:this.props.time};//time属性作为组件的time的状态值
},
render: function() {
return <h1>Hello Message {this.state.time}!</h1>;
}
});
总结
一个React组件,提供了两个接口、一个方法、三个对象。
两个接口:
- render
- getInitialState
其中render用于组件的呈现,在调用方法this.setState(state)
时会被自动调用。getInitialState
用于返回组件内部的初始状态,可以使用属性值作为组件状态。
一个方法:
- setState(state)
该方法用于重新设置组件的状态值,并且根据需要触发render
。
三个对象:
- state
- props
- propTypes
其中state
存储的组件状态,可以能过setState
进行修改;
props存储的组件属性,不能被修改;同时,props包含一个特列对象:props.children
,该对象中包含的时子对象。
propTypes
为一个JS对象,该对象用于校验组件的属性是否正在确。