组件分类
react组件分为有状态和无状态的两种类别,有状态的一般是类组件,无状态的是函数组件
注意:组件首字母必须大写,否则按照普通标签解析
函数组件
先来看代码:
function Clock(props) {
return (
<div>
<h1>Hello, world!</h1>
<h2>现在是 {props.date.toLocaleTimeString()}.</h2>
</div>
);
}
ReactDOM.render(<Clock date={new Date()} />,document.getElementById('example'));
该组件返回一个<div>
标签,在后面渲染到example节点上,组件接收一个参数props
,这是react的默认参数,表示从组件标签上传递过来的值
注意:函数组件在每次渲染时会重新执行一遍,所以!如果在函数中定义的属性,每次执行都会初始化,并不会随着渲染周期自动改变!
如图所示:preCount无法跨渲染周期!如何解决这个问题???可以使用ref来跨渲染周期!
类组件
先看代码:
class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>现在是 {this.props.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(<Clock date={new Date()} />,document.getElementById('example'));
两种组件的最大区别就是,类组件内部有个state
用于标识组件状态,所以,如果在选择上,需要使用state来保存状态或内容,推荐使用类组件进行构建
组件传值
在传值时有两种方式:
函数组件传值通过函数内部全局变量props
获取
类组件传值通过this.props
获取
传值时自定义参数名必须和取值时相同,如:
// 传递
<Alert msg={'abc'}/>
// 取值
// props.msg or this.props.msg
注意:props是只读的
Contex参数传递
React.js 的 context 就是这么一个东西,某个组件只要往自己的 context 里面放了某些状态,这个组件之下的所有子组件都直接访问这个状态而不需要通过中间组件的传递。一个组件的 context 只有它的子组件能够访问,它的父组件是不能访问到的,你可以理解每个组件的 context 就是瀑布的源头,只能往下流不能往上飞。
使用context
进行参数传递:可以将父组件需要共享的参数直接传递给需要该参数的子组件
方法:
父组件中必须定义一个方法一个静态校验属性:
getChildContext(){
return {
color:this.state.color
}
}
static childContextTypes={
color:ReactPropTypes.string
}
在需要使用的子组件中校验字段:
static contextTypes={
color:ReactPropTypes.string
}
然后子组件直接使用该属性:this.context.color
即可
参数校验
默认参数
当组件需要一些必要的参数传递时,可以设置以下默认值:static defaultProps={}
,当调用该组件的时候没有传递必要值时会用默认值来代替
class HelloMessage extends React.Component {
render() {
return (
<h1>Hello, {this.props.name}</h1>
);
}
}
HelloMessage.defaultProps = {
name: 'Runoob'
};
const element = <HelloMessage name="pp"/>;
ReactDOM.render(
element,
document.getElementById('example')
);
校验参数
如果需要限制传参的类型,可以设置:static propTypes={}
,可以对传递参数做类型校验(必须安装react提供的校验包:prop-types
,react 15后需要)
简易用法:
import ReactPropTypes from 'prop-types'
class HelloMessage extends React.Component {
static propTypes={abc:ReactPropTypes.number}
render() {
return (
<h1>Hello, {this.props.abc}</h1>
);
}
}
验证器
React.Proptypes在react15.5后移到prop-types库中:
<script src="https://cdn.bootcss.com/prop-types/15.6.1/prop-types.js"></script>
使用验证器方式:
方式一:组件外部设置
class MyTitle extends React.Component {
render() {
return (
<h1>Hello, {this.props.title}</h1>
);
}
}
{/*第一种方式,以设置属性方式*/}
MyTitle.propTypes = {
title: PropTypes.string
};
ReactDOM.render(
<MyTitle title={'abc'} />,
document.getElementById('example')
);
方式二:在创建类时设置
class TodoItem extends React.Component {
static propTypes = {//类的静态属性
name: React.PropTypes.string
};
static defaultProps = {//类的静态属性
name: ''
};
...
}
其他的更多验证器:仅供参考
MyComponent.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!');
}
}
}
}