1.props简介当React遇到一个元素是用户定义的组件时,它会将JSX属性作为一个称为“props”的对象传递给组件。函数声明的组件会接受一个props参数来获取属性传递的参数functionComponentA(props){return
IamcomponentB:{props.value}
}如果函数组件需要props函数,必须不能缺少形参类的声明。在react构建中,使用constructor获取Component类的props属性。当组件继承父类props时,可以通过this.props属性名传递属性值classComponentBextendsReact.Component{constructor(props){super(props);}render(){return
我是组件B的继承子类{this.props.name}
}}必须在constructor方法中调用super方法,否则创建时会报错新实例。这是因为子类的this对象必须先通过父类的构造函数进行整形,获得与父类相同的实例属性和方法,然后再处理添加子类自身的实例属性和方法。如果不调用super方法,子类就无法获取到这个对象。注意:props可以传递任何数据类型,并且props是只读的(单项数据流),所有React组件都必须像纯函数一样使用它们的props。2.props批量投放的场景:有时候我们需要传递的参数不止一个,如果全部都写的话,也许你能接受10个,那100个、1000个又如何呢。那你的代码简直了不起。在本例中,我们借用了ES6中的扩展运算符(...),即三个点。我们直接先定义传递的参数,然后传递。类Person扩展React.Component{render(){console.log(this);//Person实例对象const{name,age,sex}=this.props;return(
- 姓名:{name}
- 性别:{sex}
- 年龄:{age}
)}}//单程ReactDOM.render(
,document.getElementById('test'))ReactDOM.render(
,document.getElementById('test1'))//批量投放constp={name:'老王',age:30,sex:'man'}ReactDOM.render(
,document.getElementById('test2'))3.props的验证随着应用越来越大,通常你希望每个props都有一个指定的值类型,这样你就可以捕获大量通过类型检查发现错误,方便开发,减少异常维护时间。组件的props属性校验,需要配置组件的特殊静态propTypes属性,配合prop-types三方库实现prop校验。(prop-types是react脚手架自带的,不需要下载)16版本之前16、单独作为库使用方法一:为类组件设置属性propTypesimportReact,{Component}from'react'importPropTypesfrom'prop-types'classComponentAextendsComponent{render(){//因为jsxelements本质上是React.createElement()被隐式调用//所以如果你的js文件包含jsx元素,你必须导入React来支持jsx元素的隐式调用,否则编译器会报错//'React'mustbein使用JSX返回时的作用域(
name:{this.props.name}
age:{this.props.age}
)}}ComponentA.propTypes={name:PropTypes.string,age:PropTypes.number}exportdefaultComponentA使用类静态属性语法(static)来设置propTypes,它的类添加的属性自己。importReact,{Component}from'react'importPropTypesfrom'prop-types'classComponentAextendsComponent{staticpropTypes={name:PropTypes.string,age:PropTypes.number}render(){//因为jsx元素本质上是它被React.createElement()隐式调用//所以如果你的js文件中包含jsx元素,你必须引入React来支持jsx元素的隐式调用,否则编译器会报错//'React'mustbeinscope使用JSX时return(
name:{this.props.name}
age:{this.props.age}
)}}exportdefaultComponentAdefaultpropertyvalue,当没有传递属性时,使用你定义的值//指定默认标签属性值Person.defaultProps={sex:'male',age:17}函数组件通过为构造函数props设置属性来支持组件验证importReact,{Component}from'react'importPropTypesfrom'prop-types'classComponentAextendsComponent{staticpropTypes={name:PropTypes.string,age:PropTypes.number}render(){//因为jsx元素本质上是React.creatElement()被隐式调用//所以如果你的js文件包含jsx元素,你必须导入React以支持jsx元素被隐式调用,否则编译器会报错//'React'mustbeinscopewhenusingJSXreturn(
name:{this.props.name}
age:{this.props.age}
)}}exportdefaultComponentA四、类组件Ifconstructor和props不初始化状态或执行方法绑定,不需要为React组件实现构造函数。在挂载React组件之前,将调用其构造函数。当为React.Component子类实现构造函数时,super(props)应该在其他语句之前被调用。否则,this.props可能在构造函数中有未定义的错误。通常,在React中,构造函数仅在两种情况下使用:通过将对象分配给this.state来初始化内部状态。为事件处理程序绑定一个实例(绑定改变了这个点)//stateconstructor(props)的基本使用{super(props);//初始化状态this.state={isHot:true,wind:'gale'}//bind:做两件事-生成一个新函数并将this更改为Weather的实例对象//this.changeWeather是一个方法原型。通过绑定更改此后,将生成一个新方法并将其放置在实例本身上。结果实例中也多了一个changeWeather方法,这样就可以调用this.changeWeather=this.changeWeather.bind(this);}传递props和不传递props的区别classPersonextendsReact.Component{//1.传递props也传递给superconstructor(props){//console.log(props)super(props);控制台日志(this.props);//组件传入的所有props如:{name:"Tom",sex:"Male",age:17,speak:?}}//2.传入props但不传入superconstructor(props){//console.log(props)super();console.log(this.props);//未定义的console.log(props);//组件传入的所有props如:{name:"Tom",sex:"Male",age:17,speak:?}}//3.不要传constructor(){//console.log(道具)超级();控制台日志(this.props);//undefined}}参考前端高级面试题详细答案总结:构造函数是否接收props,是否传递给super,取决于:是否要在构造函数中通过this访问props五、使用三方库prop-types基本类型验证PropTypesDemo.propTypes={propsArray:PropTypes.array,//数组propsObject:PropTypes.object,//对象propsString:PropTypes.string,//字符串propsNumber:PropTypes.number,//数字propsBool:PropTypes.bool,//布尔值propsSymbol:PropTypes.symbol,//私有数据类型propsFunc:PropTypes.func,//函数//节点数据类型(任何可以渲染的数据类型)propsNode:PropTypes.node,//reactelement(jsx)propsElement:PropTypes.element,}Reactobjectboolsymbolfunc不能直接在页面上渲染。这些数据类型不属于节点类型。必填属性修饰符isRequiredprop-types所有类型后面都可以跟isRequired修饰符,表示该属性是必填属性。PropTypesDemo.propTypes={propsArray:PropTypes.array.isRequired,//必须传递数组类型propsElement:PropTypes.element.isRequired//必须传递元素类型propsAny:PropTypes.any.isRequired//必须传递任何数据类型}prop-types还提供了一个any数据类型表示Any数据类型,该类型主要配合isRequired修饰符使用,表示当前属性不能为空复杂类型验证PropTypesDemo.propTypes={//数据是指定构造函数propsCurrentProto的实例:公关opTypes.instanceOf(Dog),//属性值为指定值之一propsOneOf:PropTypes.oneOf(['Male','Female']),//属性的数据类型为指定值之一typespropsOneOfType:PropTypes.oneOfType([PropTypes.array,PropTypes.object,PropTypes.instanceOf(RegExp),PropTypes.oneOf(['Male','Female'])]),//ArraypropsStringArray指定每个的数据类型item:PropTypes.arrayOf(PropTypes.string),//指定每个键值对的对象propsDateObj值数据类型:PropTypes.objectOf(PropTypes.instanceOf(Date)),//指定键值数据类型对象propsCurrentObject:PropTypes.shape({name:PropTypes.string,//这个属性可以是默认值age:PropTypes.number.isRequired//这个属性必须存在于当前对象中})}除了instanceOf,oneOf,其他几个验证规则可以相互嵌套,上面的验证规则仍然可以使用isRequired修饰符。可以在React组件的propTypes属性中指定自定义的验证规则,可以设置一个验证函数来实现一些自定义的验证规则。自定义验证函数一般接收三个参数:props、propName、componentName。props:当前组件接收的属性参数的对象集合propName:使用当前自定义规则的属性名称componentName:当前组件名称。当接收到的props的属性值不通过校验规则时,只需要向函数外部返回一个Error实例对象即可。好吧。案例:实现自定义校验规则,传入数据必须是字符串或数字,字符串不能包含“fxxk”敏感字符,数字必须大于等于18小于等于120。ComponentC.propTypes={propsA:function(props,propName,componentName){letval=props[propName]if(typeofval==='string'){if(/fxxk/.test(val)){返回新错误(`Component:${componentName},${val}中的属性"${propName}"值包含敏感字符`)}}elseif(typeofval==='number'){if(val<18||val>120){returnnewError(`Component:${componentName},${val}中属性“${propName}”的值不满足18-120的范围`)}}else{returnnewError(`组件:${componentName},属性“${propName}”的值不是字符串或数字`)}}}使用arrayOf或ObjectOf定义验证规则使用可以作为参数传递给的自定义验证函数prop-types库的arrayOf或ObjectOfrary对数组和对象执行遍历验证。此时验证规则函数接收5个参数:propValue、key、c??omponentName、location、propsFullNamepropValue:当前验证的数组或对象本身key:遍历数组的下标或对象的键值componentName:当前组件名location:当前值位置常量"prop"propsFullName:遍历当前项的全字符串名Example:propsCustomArrayOf[2],propsCustomArrayOf.namePropTypesDemo.propTypes={//arrayOforObjectOf自定义验证规则propsCustomArrayOf:PropTypes.arrayOf(function(propValue,key,componentName,location,propsFullName){if(!/matchme/.test(propValue[key])){returnnewError(`Failedproptype:Invalidprop'${propsFullName}'提供给${componentName}.Validationfailed.`)}}),propsCustomObjectOf:PropTypes.objectOf(function(propValue,key,componentName,location,propsFullName){if(!/matchme/.test(propValue[key])){返回新错误(`失败的道具类型:提供给${componentName}的道具“${propsFullName}”无效。验证失败。`)}}),}6.小总结每个组件对象都会有组件标签所有属性的props(properties的简称)属性所有的属性都保存在props中,变化的数据通过label属性从组件外部传递到组件内部。注意:不要修改组件内部的props数据。使用propTypes属性,配合prop-types三方库实现prop校验(无需单独下载,脚手架中已经集成)