1. 认识props
1.1 理解组件传参
组件通常非常强的可复用性.但是如果组件每次返回的都是同一个React元素,那么组件的扩展性将会变差
如果想要提升组件的扩展性,在我们不知道组件被调用时难免要使用父组件指定的参数.
然后根据父组件传递的不同数据展示不同的内容
因此:
-
每个组件对象都会有props(properties)属性
-
组件标签在被使用时所有属性都会保存在props中,props是一个对象
1.2 组件传参的作用
父组件在使用子组件时通过标签属性从子组件外向组件内传递变化的数据
1.3 props 的只读性
React 非常灵活,但它也有一个严格的规则:
所有 React 组件都必须像纯函数一样保护它们的 props 不被更改。
2. props的基本使用
2.1 父组件组件的传参方式
props组件间的传参两种方式
-
通过闭合单标签组件的属性传递 参数
<Nav title="标题" name="username" />
-
通过双标签组件内包裹的标签传递参数
<Nav> <span>组件的子组件</span> </Nav>
2.2 子组件接受父组件参数说明
说明:
- 子组件接受通过props接受父组件的参数
- 函数组件通过第一个形参props接受父组件参数,
- class组件在会将
props
作为组件实例的属性,因此在class组件中通过this.props
获取参数
2.3 子组件接受通过属性属性传参
传参的示例:
<Nav title="标题" name="username" />
示例代码如下:
// 1. 子组件接受父组件参数
// 1.1函数组件接受父组件参数
function MyStudent(props){
console.log(props);
// {name: "张三", age: 18, sex: "男"}
return (
<ul>
<li>姓名: {props.name}</li>
<li>年纪: {props.age}</li>
<li>性别: {props.sex}</li>
</ul>
)
}
// 1.2 class组件接受参数
class MyTeacher extends React.Component{
render(){
return (
<ul>
<li>姓名: { this.props.name }</li>
<li>年纪: { this.props.age }</li>
<li>性别: { this.props.sex }</li>
</ul>
)
}
}
// 2. 父组件, 展示人员信息
class MyCom extends React.Component{
render(){
let student = {
name:"张三",
age:18,
sex:"男"
}
let teacher = {
name:"李四",
age:34,
sex: "男"
}
return (
<div>
<h2>学生信息</h2>
{/* 父组件通过属性向子组件传递数据*/}
<MyStudent
name={student.name}
age={student.age}
sex={student.sex}
/>
<h2>老师信息</h2>
{/* 使用扩展运算符,将对象扩展出来 */}
<MyTeacher {...teacher}/>
</div>
)
}
}
// 渲染内容
ReactDOM.render(<MyCom/>, document.getElementById("app"))
示例说明:
- 父组件在使用子组件时,可以通过正常的标签属性传参
- 也可以通过
...
扩展运算符将对象数据扩展开, - 因为props最后会将所有的属性参数合并为对象接受
2.4 接受通过组件标签嵌套内容传参
标签嵌套传参说明:
- 父组件通过组件名标签的方式调用子组件例如:
<Nav></Nav>
- 父组件在调用子组件时可以在标签中嵌套内容,例如:
<Nav>李四</Nav>
- 标签嵌套的所有内容都将会作为props的children属性的值
传参的方式:
<Nav>
<span>组件的子组件</span>
</Nav>
获取参数示例代码:
function MyButton(props){
console.log(props);
// {children: "按钮"}
// {children: "点击"}
// {children: "切换"}
return (
<button>{ props.children }</button>
)
}
// 2. 父组件
class MyCom extends React.Component{
render(){
return (
<div>
<MyButton>按钮</MyButton>
<MyButton>点击</MyButton>
<MyButton>切换</MyButton>
</div>
)
}
}
ReactDOM.render(<MyCom/>, document.getElementById("app"))
示例说明:
- 组件被调用时所包裹的内容会被props的children属性所接受
- 这样使用的好处就是如果如组件需要给子组件传递标签
- 通过嵌套的 方式会显得更加自然,更符合html开发习惯
示例代码:
通过props传递标签内容
// 无状态组件(函数组件)
function Wuwei(props){
return (
<div className={"wuwei haiwen-" + props.color}>
{props.children}
</div>
)
}
// 状态组件(class组件)
class Haiwen extends React.Component {
/*
注意:
contructor 中的props如果不在constructor中使用this.props,可以不传
但是官方建议不管是不是用都传props
*/
constructor(props){
super(props)
}
render() {
return (
<Wuwei color="blur">
<h2>Hello World</h2>
<h4>This is wuwei</h4>
</Wuwei>
)
}
}
ReactDOM.render(< Haiwen />,document.getElementById('example'))
3. 关于其他props的操作
3.1 对于props接受数据的验证
对于数据的类型和必要性进行验证
注意:
自 React v15.5 起,
React.PropTypes
已移入另一个包中。请使用prop-types
库 代替。
3.1.1 引入prop-types
<script src="./js/prop-types.js"></script>
3.1.2 验证数据
验证数据说明:
- 通过组件调用
propTypes
, 属性值为对象 - 对象中定义不同字段接受的数据类型,以及是否必传
函数组件验证的示例代码:
function MyStudent(props){
console.log(props);
return (
<ul>
<li>姓名: {props.name}</li>
<li>年纪: {props.age}</li>
<li>性别: {props.sex}</li>
</ul>
)
}
// 通过组件调用propTypes 值为验证数据的对象
// isRequired表示这个字段为必传项
MyStudent.propTypes = {
name: PropTypes.string.isRequired, // name:string类型必传
age: PropTypes.number.isRequired, // age: number类型,必传
sex: PropTypes.string // sex: string类型,非必传
}
// 2. 父组件
class MyCom extends React.Component{
render(){
let student = {
name:"张三",
age:18,
sex:"男"
}
return (
<div>
<h2>学生信息</h2>
<MyStudent
name={student.name}
age={student.age}
sex={student.sex}
>span</MyStudent>
</div>
)
}
}
说明:
- 函数组件只能通过组件名调用
propTypes
的方式验证数据 - class组件可以将验证定义为静态方法
class组件验证数据的简写方式
// 1 class组件接受参数
class MyTeacher extends React.Component{
// class组件验证数据, 定义为静态属性
static propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number.isRequired,
sex: PropTypes.string
}
render(){
return (
<ul>
<li>姓名: { this.props.name }</li>
<li>年纪: { this.props.age }</li>
<li>性别: { this.props.sex }</li>
</ul>
)
}
}
// 2. 父组件
class MyCom extends React.Component{
render(){
let teacher = {
name:"李四",
age:34,
sex: "男"
}
return (
<div>
<h2>老师信息</h2>
<MyTeacher {...teacher}/>
</div>
)
}
}
3.2 数据默认值
说明:
- 通过组件的
defaultProps
来定义默认值 - 定义数据默认值,就是当父组件未通过props传递数据是使用的默认值
- 定义默认值的数据也可以定义必传项,不冲突,如果未传数据,还是会启用默认值
3.2.1 函数组件定义默认值
示例代码:
function MyStudent(props){
console.log(props);
return (
<ul>
<li>姓名: {props.name}</li>
<li>年纪: {props.age}</li>
<li>性别: {props.sex}</li>
</ul>
)
}
// 函数组件定义默认值
MyStudent.defaultProps = {
name:"王五",
age:20,
sex:"男"
}
// 2. 父组件
class MyCom extends React.Component{
render(){
let student = {
name:"张三",
age:18,
sex:"男"
}
return (
<div>
<h2>学生信息</h2>
<MyStudent
name={student.name}
age={student.age}
sex={student.sex}
>span</MyStudent>
</div>
)
}
}
3.2.2 class组件通过静态属性定义默认值
示例代码:
class MyTeacher extends React.Component{
// class组件验证数据
static propTypes = {
name: PropTypes.string,
age: PropTypes.number,
sex: PropTypes.string
}
// class 组件限定数据的默认值
static defaultProps = {
name:"王五",
age:20,
sex:"男"
}
render(){
return (
<ul>
<li>姓名: { this.props.name }</li>
<li>年纪: { this.props.age }</li>
<li>性别: { this.props.sex }</li>
</ul>
)
}
}
// 2. 父组件
class MyCom extends React.Component{
render(){
let teacher = {
name:"李四",
age:34,
sex: "男"
}
return (
<div>
<h2>老师信息</h2>
<MyTeacher {...teacher}/>
</div>
)
}
}
说明:
推荐用静态属性, 这样看起来和组件是一体的, 但是注意ES6 并没有实现静态属性, 可能是后面版本实现的, 不过我们不用担心, 因为react 会使用babel编译
网友评论