React: React的属性验证机制

一、简介

在开发中,属性变量类型的验证,几乎是任何语言都必须关注的问题,因为如果传入的数据类型不对,轻者程序运行仅仅是给出警告⚠️,严重的会直接导致程序中断,APP闪退或者web页面挂掉,这是很严重的bug问题。如我们所知,JavaScript是一种弱类型的语言,这意味着开发者可以随意地修改变量值的数据类型,而且JavaScript虚拟机对此操作并不会产生异议,虽然这种机制大大地提高了编程的灵活性,但是也隐藏了一个极大的crash风险。React组件为此提供了一种声明和验证属性类型的方法,称为自动属性验证机制。这种机制将会大幅度减少调试时间,能够及时把不正确的属性类型触发警告⚠️,以便开发者准确快速的定位bug,然后进行修复。

 

二、验证器类型

React内置了自动属性验证器,如下所示:

数组类型     React.PropTyps.array

布尔类型     React.PropTyps.bool

函数类型     React.PropTyps.func

数字类型     React.PropTyps.number

对象类型     React.PropTyps.object

字符串类型   React.PropTyps.string

React也支持自定义属性验证器,可以使用typeof字段和“===”进行判断并抛出异常,例如:

布尔类型 (props, propName) => (typeof props[propName] === "boolean") ?  null : new Error(`${propName} is not boolean`)

函数类型 (props, propName) => (typeof props[propName] === "function") ?  null : new Error(`${propName} is not function`)

数字类型 (props, propName) => (typeof props[propName] === "number") ?  null : new Error(`${propName} is not number`)

对象类型 (props, propName) => (typeof props[propName] === "object") ?  null : new Error(`${propName} is not object`)

字符串类型 (props, propName) => (typeof props[propName] === "string") ?  null : new Error(`${propName} is not string`)

字符类类型和长度限制嵌套 (props, propName) =>
(typeof props[propName] === 'string') ?
((props[propName].length > 5) ? new Error("长度超过5") : null) : new Error(`${propName} is not sring`)

 

三、验证器声明

React中对属性类型的声明使用了关键字propTypes。对于createClass组件、ES6类组件和无状态函数式组件,它们的声明方式有所区别,如下所示:

createClass组件:

//创建组件
const Component = React.createClass({
    //属性验证声明
    propTypes: {
        title: React.PropTypes.string,
        items: React.PropTypes.array
    }
   .........   })

ES6类组件:

//创建组件
class Component extends React.Component{
    .........     
}
//属性验证声明
Component.propTypes = {
    title: React.PropTypes.string, 
    items: React.PropTypes.array
}

无状态函数式组件:

//创建组件
const Component = ({title,items}) => {
    .......
}
//属性验证声明
Component.propTypes = {
    title: React.PropTypes.string,
    items: React.PropTypes.array
}

 

四、验证器属性限制

React中,在没有提供属性数据的情况下渲染组件会导致JavaScript报错,从而拖垮整个Web应用。对于这种数据缺少的错误,React属性验证器提供了isRequired字段要求属性数据是必须项,如果不填或者为空,React将会在触发错误之前就在控制台发出警告信息,提醒开发者异常原因。如下:

//创建组件
const Component = React.createClass({
    //属性验证声明
    propTypes: {
        title: React.PropTypes.string.isRequired,
        items: React.PropTypes.array.isRequired
    }
   .........  
})

 

五、简单示例

需求: 定一个动物组件,拥有种族类型属性type,动物数组属性kinds,在Web页面上展示type标题和kinds个数。

1、传入正确的数据,动物数组个数显示正常: 

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Hello React</title>
    <script src="react/react.js"></script>
    <script src="react/react-dom.js"></script>
    <script src="react/browser.min.js"></script>
</head>
<body>
    <div id="container"></div>
    <script type="text/babel">

        const AnimalComponent = React.createClass({
            render(){
                const {type, kinds} = this.props
                const divStyle = {
                    width:400,
                    height:100,
                    backgroundColor:"#DAE",
                    color:"red",
                    textAlign:"center"
                }
                return (
                    <div className="animal" style={divStyle}>
                        <h1>{type}</h1>
                        <p>
                            <span>{kinds.length} kinds animals</span>
                        </p>
                    </div>
                )
            }
        })

        const kinds = ["cat","dog","pig","Cattle","sheep"]
        ReactDOM.render(
            <AnimalComponent type="Breastfeeding animation" kinds={kinds} />,
            document.getElementById("container")
        )

    </script>
</body>
</html>

2、如果将数组kinds当做字符串传入,Web页面虽然没有挂掉,但是动物数组个数却显示异常,如果开发者检查不仔细,那就是线上的bug了:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Hello React</title>
    <script src="react/react.js"></script>
    <script src="react/react-dom.js"></script>
    <script src="react/browser.min.js"></script>
</head>
<body>
    <div id="container"></div>
    <script type="text/babel">


        const AnimalComponent = React.createClass({
            render(){
                const {type, kinds} = this.props
                const divStyle = {
                    width:400,
                    height:100,
                    backgroundColor:"#DAE",
                    color:"red",
                    textAlign:"center"
                }
                return (
                    <div className="animal" style={divStyle}>
                        <h1>{type}</h1>
                        <p>
                            <span>{kinds.length} kinds animals</span>
                        </p>
                    </div>
                )
            }
        })

        const kinds = "this is a cat"
        ReactDOM.render(
            <AnimalComponent type="Breastfeeding animation" kinds={kinds} />,
            document.getElementById("container")
        )


    </script>
</body>
</html>
View Code

3、如果此时添加属性验证器,再将数组kinds当做字符串传入,Web页面没有挂掉的同时,控制台还会爆出警告,可以及时发现数据问题:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Hello React</title>
    <script src="react/react.js"></script>
    <script src="react/react-dom.js"></script>
    <script src="react/browser.min.js"></script>
</head>
<body>
    <div id="container"></div>
    <script type="text/babel">


        const AnimalComponent = React.createClass({

            propTypes: {
                type: React.PropTypes.string,
                kinds: React.PropTypes.array
            },

            render(){
                const {type, kinds} = this.props
                const divStyle = {
                    width:400,
                    height:100,
                    backgroundColor:"#DAE",
                    color:"red",
                    textAlign:"center"
                }
                return (
                    <div className="animal" style={divStyle}>
                        <h1>{type}</h1>
                        <p>
                            <span>{kinds.length} kinds animals</span>
                        </p>
                    </div>
                )
            }
        })

        const kinds = "this is a cat"
        ReactDOM.render(
            <AnimalComponent type="Breastfeeding animation" kinds={kinds} />,
            document.getElementById("container")
        )


    </script>
</body>
</html>
View Code

4、如果此时添加属性验证器的同时,还限制属性是isRequried,那么在渲染组件时,不传递参数,Web页面直接会挂掉成空白页了,当然可以提前设置默认参数避免这种问题:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Hello React</title>
    <script src="react/react.js"></script>
    <script src="react/react-dom.js"></script>
    <script src="react/browser.min.js"></script>
</head>
<body>
    <div id="container"></div>
    <script type="text/babel">


        const AnimalComponent = React.createClass({

            propTypes: {
                type: React.PropTypes.string.isRequired,
                kinds: React.PropTypes.array.isRequired
            },

            render(){
                const {type, kinds} = this.props
                const divStyle = {
                    width:400,
                    height:100,
                    backgroundColor:"#DAE",
                    color:"red",
                    textAlign:"center"
                }
                return (
                    <div className="animal" style={divStyle}>
                        <h1>{type}</h1>
                        <p>
                            <span>{kinds.length} kinds animals</span>
                        </p>
                    </div>
                )
            }
        })

        ReactDOM.render(
            <AnimalComponent/>,
            document.getElementById("container")
        )


    </script>
</body>
</html>
View Code

5、如果此时添加自定义的属性验证器,再将数组kinds当做字符串传入,Web页面没有挂掉的同时,控制台还可以弹出自定义的警告信息:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Hello React</title>
    <script src="react/react.js"></script>
    <script src="react/react-dom.js"></script>
    <script src="react/browser.min.js"></script>
</head>
<body>
    <div id="container"></div>
    <script type="text/babel">

        const AnimalComponent = React.createClass({

            propTypes: {
                type: React.PropTypes.string,
                kinds: (props, propName) =>
                        (typeof props[propName] === 'string') ? new Error(`${propName} is not array`) : null
            },

            render(){
                const {type, kinds} = this.props
                const divStyle = {
                    width:400,
                    height:100,
                    backgroundColor:"#DAE",
                    color:"red",
                    textAlign:"center"
                }
                return (
                    <div className="animal" style={divStyle}>
                        <h1>{type}</h1>
                        <p>
                            <span>{kinds.length} kinds animals</span>
                        </p>
                    </div>
                )
            }
        })

        const  kinds = "this is a cat"
        ReactDOM.render(
            <AnimalComponent type="Breastfeeding animation" kinds={kinds} />,
            document.getElementById("container")
        )


    </script>
</body>
</html>
View Code

 

posted @ 2019-12-05 15:57  XYQ全哥  阅读(728)  评论(0编辑  收藏  举报