目录
12. 特定 shape 参数的对象(所传的props中可包含这个属性,允许有额外的属性)
13. 特定 exact 参数的对象(所传的props中可包含这个属性,不允许有额外的属性)
14. 任意的类型加上isRequired都表示该props必传
17. node,可以被渲染的对象 numbers, strings, elements 或 array
前言:
需要注意的是,在React v15.5版本之后,props的验证已经转移到了prop-types库中。
如果之前写过vue项目的,在关于组件传值这块,我们一般都会为props设置它的类型,是string或者number或者object等等,还会去给它一个default默认值,如果此参数必传,会把required设置为true等等这些,其实设置这些验证的作用主要是为了更加规范数据,以此来确保我们的程序,组件可以按照预想的那样正常的执行使用,当我们传入不符合验证规则的数据时,控制台就会直接抛出错误,警告开发者,我们这么做是不对的,所以,熟练掌握这个是十分有必要的
所以,我们需要引入这个库,对于使用create-react-app创建的react项目,需要使用npm 安装prop-types库:
npm install --save prop-types
对于使用html,引入cdn js库的,我们需要这样引入
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.8.1/prop-types.min.js"></script>
大概代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app"></div>
</body>
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.8.1/prop-types.min.js"></script>
<script type="text/babel">
const app = document.getElementById('app')
class Person extends React.Component {
render() {
return (
<div>
<ul>
<li>需求任你提,我改算我输</li>
</ul>
</div>
);
}
}
Person.propTypes = {
//待验证的props值
}
ReactDOM.render(<Person/>, app)
</script>
</html>
看看页面输出:
props验证:
1. 任意值
顾名思义,这个值是什么类型,我不管,你随便!
Person.propTypes = {
//待验证的props值
id: PropTypes.any, //任意值
}
ReactDOM.render(<Person id={'999'}/>, app)
2. 字符串类型
Person.propTypes = {
//待验证的props值
name: PropTypes.string, //字符串
}
ReactDOM.render(<Person name={'Jay丶千珏'}/>, app)
3. 数字类型
Person.propTypes = {
//待验证的props值
age: PropTypes.number, //数字
}
ReactDOM.render(<Person age={25}/>, app)
4. 布尔值
Person.propTypes = {
//待验证的props值
isLikeApple: PropTypes.bool, //布尔值
}
ReactDOM.render(<Person isLikeApple={true}/>, app)
5. 数组
Person.propTypes = {
//待验证的props值
hobby: PropTypes.array, //数组
}
ReactDOM.render(<Person hobby={['打篮球', '听音乐']}/>, app)
6. 对象
Person.propTypes = {
//待验证的props值
family: PropTypes.object, //对象
}
ReactDOM.render(<Person family={{mom: 'mom', dad: 'dad'}}/>, app)
7. 函数
由于function在js中属于关键字,所以在react中,props类型为方法时,设置为了func
Person.propTypes = {
//待验证的props值
say: PropTypes.func, //函数
}
function say() {
return 'hello word!'
}
ReactDOM.render(<Person say={say}/>, app)
8. 只接受指定的值(oneOf)
我指定了sex为男或者女,如果我不传递这两个值之一
Person.propTypes = {
sex: PropTypes.oneOf(['男', '女'])
}
ReactDOM.render(<Person sex={'123'}/>, app)
9. 可以是多个对象类型中的一个(oneOfType)
这里height的值应为string或者number,但是我传递了一个true布尔值,故
Person.propTypes = {
height: PropTypes.oneOfType([ //身高可以是数字也可以是字符串 最后总需要拼接公分
PropTypes.string,
PropTypes.number
]),
}
ReactDOM.render(<Person height={true}/>, app)
10. 指定类型组成的数组(arrayOf)
这里的idol必须传递一个内部元素全部是string类型组成的数组,但是我在里面传递了一个number:999
Person.propTypes = {
idol: PropTypes.arrayOf(PropTypes.string), //这里喜欢的明星偶像都必须是字符串类型的
}
ReactDOM.render(<Person idol={['Jay', 'Vae', 999]}/>, app)
11. 指定类型的属性构成的对象(objectOf)
各个学科的分数必须为数字,但是我却在语文的分数写成了字符串100,看控制台输出
Person.propTypes = {
fraction: PropTypes.objectOf(PropTypes.number), //这里各个科目的成绩必须是数字
}
ReactDOM.render(<Person fraction={{'yuwen': '100', 'shuxue': 100, 'yingyu': 100}}/>, app)
12. 特定 shape 参数的对象(所传的props中可包含这个属性,允许有额外的属性)
Person.propTypes = {
foods: PropTypes.shape({
lunch: PropTypes.string
}),
}
ReactDOM.render(<Person foods={{lunch: '大米饭', dinner: '面条'}}/>, app)
13. 特定 exact 参数的对象(所传的props中可包含这个属性,不允许有额外的属性)
包含name1和name2两个属性值,并不包含name3,但是我传递了name3,看看结果
Person.propTypes = {
game: PropTypes.exact({
name1: PropTypes.string,
name2: PropTypes.string
}),
}
ReactDOM.render(<Person game={{name1: 'lol', name3: 'NBA2K'}}/>, app)
14. 任意的类型加上isRequired都表示该props必传
Person.propTypes = {
city: PropTypes.string.isRequired,
}
ReactDOM.render(<Person/>, app)
其实当我在ws上写这段代码的时候,编辑器已经提醒我了,表示city是必传的,但是我没传递
15. 自定义验证
设置了邮箱格式的正则表达式,传递的 qianjue7012 很显然不是个邮箱格式,结果:抛出我们自定义的错误
请注意:如果验证失败需要返回一个 Error 对象。不要直接使用 `console.warn` 或抛异常,因为这样 `oneOfType` 会失效。
Person.propTypes = {
email: function (props, propName, componentName) {
const rule = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/
if (!rule.test(props[propName])) {
return new Error('Email format error')
}
}
}
ReactDOM.render(<Person email={'qianjue7012'}/>, app)
16. element元素
Person.propTypes = {
slogan: PropTypes.element
}
ReactDOM.render(<Person slogan={<h2 style={{display: 'inline', color: '#ff0000'}}>需求任你提,我改算我输</h2>}/>, app)
17. node,可以被渲染的对象 numbers, strings, elements 或 array
依然是这个slogan这个属性,但是我传递了一个布尔值,看看结果:
Person.propTypes = {
slogan: PropTypes.node
}
ReactDOM.render(<Person slogan={true}/>, app)
结语&所有示例:
还有一些属性,我没有写示例,比如PropTypes.instanceOf(),因为到现在我还没用过。。。应该是不常见的吧,大概也就是这么多了,最后的所有例子我放最下面了!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app"></div>
</body>
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
<script src="https://cdn.bootcss.com/prop-types/15.6.1/prop-types.js"></script>
<script type="text/babel">
const app = document.getElementById('app')
class Person extends React.Component {
render() {
const {
id,
name,
age,
hobby,
family,
say,
isLikeApple,
slogan,
sex,
height,
idol,
fraction,
foods,
game,
city,
email,
element
} = this.props
console.log(this.props)
return (
<div>
<ul>
<li>id==>{JSON.stringify(id)}</li>
<li>name==>{name}</li>
<li>age===>{age}</li>
<li>hobby===>{JSON.stringify(hobby)}</li>
<li>family===>{JSON.stringify(family)}</li>
<li>say===>{say()}</li>
<li>isLikeApple===>{JSON.stringify(isLikeApple)}</li>
<li>slogan===>{slogan}</li>
<li>sex===>{sex}</li>
<li>height===>{height}公分</li>
<li>idol===>{JSON.stringify(idol)}</li>
<li>fraction===>{JSON.stringify(fraction)}</li>
<li>foods===>{JSON.stringify(foods)}</li>
<li>game===>{JSON.stringify(game)}</li>
<li>city===>{city}</li>
<li>email===>{email}</li>
<li>element===>{element}</li>
</ul>
</div>
);
}
}
Person.propTypes = {
id: PropTypes.any, //任意值
name: PropTypes.string, //字符串
age: PropTypes.number, //数字
hobby: PropTypes.array, //数组
family: PropTypes.object, //对象
say: PropTypes.func, //函数
isLikeApple: PropTypes.bool, //布尔值
slogan: PropTypes.node, //可以被渲染的对象 numbers, strings, elements 或 array
sex: PropTypes.oneOf(['男', '女']), //限制 prop 只接受指定的值
height: PropTypes.oneOfType([ //可以是多个对象类型中的一个,例如 可以是字符串也可以是数字
PropTypes.string,
PropTypes.number
]),
idol: PropTypes.arrayOf(PropTypes.string), //指定类型组成的数组,这里喜欢的明星偶像都必须是字符串类型的
fraction: PropTypes.objectOf(PropTypes.number), //指定类型的属性构成的对象,这里各个科目的成绩必须是数字
foods: PropTypes.shape({ //特定 shape 参数的对象(所传的props中必须包含这个属性,允许有额外的属性)
lunch: PropTypes.string
}),
game: PropTypes.exact({ //和shape相似,不同点在于,只能包含这个属性,不允许有额外的属性
name1: PropTypes.string
}),
city: PropTypes.string.isRequired, //任意的类型加上isRequired都表示该props必传
email: function (props, propName, componentName) {
const rule = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/
if (!rule.test(props[propName])) {
return new Error('Email format error')
}
},
element: PropTypes.element //element元素
}
ReactDOM.render(
<Person
id={'999'}
name='千珏'
age={25}
hobby={['打篮球', '听音乐']}
family={{mom: 'mom', dad: 'dad'}}
say={say}
isLikeApple
slogan={<h2 style={{display: 'inline', color: '#ff0000'}}>需求任你提,我改算我输</h2>}
sex='男'
height={180}
idol={['胡歌', 'Jay', 'Vae']}
fraction={{'yuwen': 100, 'shuxue': 100, 'yingyu': 100}}
foods={{'lunch': '大米饭', 'dinner': '面条'}}
game={{name1: 'lol'}} //{name1: 'lol', name2: 'nba2k'}:error
city='郑州'
email={'qianjue7012@163.com'}
element={<h2 style={{display: 'inline', color: '#0ad278', fontSize: '50px'}}>需求任你提,我改算我输</h2>}
/>, app)
function say() {
return 'hello word!'
}
</script>
</html>