第三节:React组件传参的props属性

1. 认识props

1.1 理解组件传参

组件通常非常强的可复用性.但是如果组件每次返回的都是同一个React元素,那么组件的扩展性将会变差

如果想要提升组件的扩展性,在我们不知道组件被调用时难免要使用父组件指定的参数.

然后根据父组件传递的不同数据展示不同的内容

因此:

  1. 每个组件对象都会有props(properties)属性

  2. 组件标签在被使用时所有属性都会保存在props中,props是一个对象


1.2 组件传参的作用

父组件在使用子组件时通过标签属性从子组件外向组件内传递变化的数据


1.3 props 的只读性

React 非常灵活,但它也有一个严格的规则:

所有 React 组件都必须像纯函数一样保护它们的 props 不被更改。


2. props的基本使用

2.1 父组件组件的传参方式

props组件间的传参两种方式

  1. 通过闭合单标签组件的属性传递 参数

    <Nav title="标题" name="username" />
    
  1. 通过双标签组件内包裹的标签传递参数

    <Nav>
        <span>组件的子组件</span>
    </Nav>
    


2.2 子组件接受父组件参数说明

说明:

  1. 子组件接受通过props接受父组件的参数
  2. 函数组件通过第一个形参props接受父组件参数,
  3. 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"))


示例说明:

  1. 父组件在使用子组件时,可以通过正常的标签属性传参
  2. 也可以通过...扩展运算符将对象数据扩展开,
  3. 因为props最后会将所有的属性参数合并为对象接受


2.4 接受通过组件标签嵌套内容传参

标签嵌套传参说明:

  1. 父组件通过组件名标签的方式调用子组件例如:<Nav></Nav>
  2. 父组件在调用子组件时可以在标签中嵌套内容,例如: <Nav>李四</Nav>
  3. 标签嵌套的所有内容都将会作为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"))


示例说明:

  1. 组件被调用时所包裹的内容会被props的children属性所接受
  2. 这样使用的好处就是如果如组件需要给子组件传递标签
  3. 通过嵌套的 方式会显得更加自然,更符合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 验证数据

验证数据说明:

  1. 通过组件调用propTypes, 属性值为对象
  2. 对象中定义不同字段接受的数据类型,以及是否必传

函数组件验证的示例代码:

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>
        )
    }
}


说明:

  1. 函数组件只能通过组件名调用propTypes的方式验证数据
  2. 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 数据默认值

说明:

  1. 通过组件的defaultProps来定义默认值
  2. 定义数据默认值,就是当父组件未通过props传递数据是使用的默认值
  3. 定义默认值的数据也可以定义必传项,不冲突,如果未传数据,还是会启用默认值


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编译

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,658评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,482评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,213评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,395评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,487评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,523评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,525评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,300评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,753评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,048评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,223评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,905评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,541评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,168评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,417评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,094评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,088评论 2 352