react学习笔记 item5 --- Props

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014607184/article/details/53240660

Props 就是properties 的缩写,我们可以使用Props把任意类型的数据传递给子组件。子组件本身不能设置它的props ,只能从父组件继承。我们来看下面一个例子:

// 示例1
var MessageBox = React.createClass({
        render:function(){  

            var msgs = [];
            this.props.messages.forEach(function(msg,index){
                msgs.push(
                    <p>码农说: {msg}</p>
                )
            });

            return (
                <div>
                    <h1>{this.props.title}</h1>
                    {msgs}
                </div>
            )
        }
    });

var title = '来自props:';
var subMessages = [
                '我会代码搬砖',
                '我会花式搬砖',
                '不说了,工头叫我回去搬砖了。。。。。。',
            ];

ReactDOM.render( <MessageBox title={title} messages={subMessages}/>, 
    document.getElementById('example')
)

上述代码中,我们通过 props 向子组件 MessageBox 传递了两个属性:titlemessages,然后在子组件中通过 this.props.titlethis.props.messages来获取相应的数据。因为this.props.messages为数组,因此调用 forEach 方法来遍历。最后效果如下:

这里写图片描述

这里有一个潜在问题,当父组件没有向子组件传递相应的 props 时,子组件无法通过this.props.key来获取相应的数据。这时就需要用到 getDefaultProps()

1、getDefaultProps()

getDefaultProps() 方法与上一节提到的 getInitialState()作用相似,不同的是getDefaultProps()props 设置默认值,而getInitialState()是为 state 设置默认值。

// 示例2
var MessageBox = React.createClass({
        getDefaultProps:function(){
                return {
                    title:'默认title:',
                    messages: ['默认的子消息'],
                }
            },

        render:function(){  

            var msgs = [];
            this.props.messages.forEach(function(msg,index){
                msgs.push(
                    <p>码农说: {msg}</p>
                )
            });

            return (
                <div>
                    <h1>{this.props.title}</h1>
                    {msgs}
                </div>
            )
        }
    });

var title = '来自props:';
var subMessages = [
                '我会代码搬砖',
                '我会花式搬砖',
                '不说了,工头叫我回去搬砖了。。。。。。',
            ];

ReactDOM.render( <MessageBox />, 
    document.getElementById('example')
)

示例2相对于示例1多了 getDefaultProps ,在getDefaultProps设置了titlemessages的默认值,当父组件没有向子组件传递props时,调用默认值,结果如下:

这里写图片描述

2、PropTypes

这里还有一个问题,当我们传入的 props数据类型与所需的数据类型不一致时,会报错。参考示例3:

//示例3
var MessageBox = React.createClass({
        getDefaultProps:function(){
                return {
                    title:'默认title:',
                    messages: ['默认的子消息'],
                }
            },

        render:function(){  

            var msgs = [];
            this.props.messages.forEach(function(msg,index){
                msgs.push(
                    <p>码农说: {msg}</p>
                )
            });

            return (
                <div>
                    <h1>{this.props.title}</h1>
                    {msgs}
                </div>
            )
        }
    });

var title = '来自props:';
var subMessages = [
                '我会代码搬砖',
                '我会花式搬砖',
                '不说了,工头叫我回去搬砖了。。。。。。',
            ];

ReactDOM.render( <MessageBox title={title} messages={title}/>, 
    document.getElementById('example')
)

例如我们在传递messages时,一不小心写成了{title},由于messages是一个数组,而{title}是字符串,字符串无法调用forEach()方法,因此会报下错误:

Uncaught TypeError: this.props.messages.forEach is not a function(…)

这时就需要对传入的props类型进行验证,Props 验证使用 propTypes,它可以保证我们的应用组件被正确使用,React.PropTypes 提供很多验证器 (validator) 来验证传入数据是否有效。当向 props 传入无效数据时,JavaScript 控制台会抛出警告。

//示例4
var MessageBox = React.createClass({
        propTypes:{
                messages: React.PropTypes.array.isRequired,
            },
        getDefaultProps:function(){
                return {
                    title:'默认title:',
                    messages: ['默认的子消息'],
                }
            },

        render:function(){  

            var msgs = [];
            this.props.messages.forEach(function(msg,index){
                msgs.push(
                    <p>码农说: {msg}</p>
                )
            });

            return (
                <div>
                    <h1>{this.props.title}</h1>
                    {msgs}
                </div>
            )
        }
    });

var title = '来自props:';
var subMessages = [
                '我会代码搬砖',
                '我会花式搬砖',
                '不说了,工头叫我回去搬砖了。。。。。。',
            ];

ReactDOM.render( <MessageBox title={title} messages={title}/>, 
    document.getElementById('example')
)

加上了 propTypes 验证之后,如果 props 类型不对时,控制台会打印警告信息:

Warning: Failed propType: Invalid prop `messages` of type `string` supplied to `MessageBox`, expected `array`.

React.PropTypes 提供很多验证器 (validator),更多验证器说明如下:

React.createClass({
  propTypes: {
    // 可以声明 prop 为指定的 JS 基本数据类型,默认情况,这些数据是可选的
   optionalArray: React.PropTypes.array,
    optionalBool: React.PropTypes.bool,
    optionalFunc: React.PropTypes.func,
    optionalNumber: React.PropTypes.number,
    optionalObject: React.PropTypes.object,
    optionalString: React.PropTypes.string,

    // 可以被渲染的对象 numbers, strings, elements 或 array
    optionalNode: React.PropTypes.node,

    //  React 元素
    optionalElement: React.PropTypes.element,

    // 用 JS 的 instanceof 操作符声明 prop 为类的实例。
    optionalMessage: React.PropTypes.instanceOf(Message),

    // 用 enum 来限制 prop 只接受指定的值。
    optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),

    // 可以是多个对象类型中的一个
    optionalUnion: React.PropTypes.oneOfType([
      React.PropTypes.string,
      React.PropTypes.number,
      React.PropTypes.instanceOf(Message)
    ]),

    // 指定类型组成的数组
    optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),

    // 指定类型的属性构成的对象
    optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),

    // 特定 shape 参数的对象
    optionalObjectWithShape: React.PropTypes.shape({
      color: React.PropTypes.string,
      fontSize: React.PropTypes.number
    }),

    // 任意类型加上 `isRequired` 来使 prop 不可空。
    requiredFunc: React.PropTypes.func.isRequired,

    // 不可空的任意类型
    requiredAny: React.PropTypes.any.isRequired,

    // 自定义验证器。如果验证失败需要返回一个 Error 对象。不要直接使用 `console.warn` 或抛异常,因为这样 `oneOfType` 会失效。
    customProp: function(props, propName, componentName) {
      if (!/matchme/.test(props[propName])) {
        return new Error('Validation failed!');
      }
    }
  },
  /* ... */
});

关于propTypes的更多信息,查看React 官网说明

3、{…props}

还可以使用JSX 的展开语告把 props 设置成一个对象,这样就不需要在标签中逐个列出 props ,通过 {…props} 就可以把props对象传递到子组件,如下示例5:

// 示例5
var MessageBox = React.createClass({
    render:function(){  
        var props = {
            title: '来自props:',
            messages: [
                        '我会代码搬砖',
                        '我会花式搬砖',
                        '不说了,工头叫我回去搬砖了。。。。。。',
                    ]
        };
        return ( 
                <Submessage {...props} />
        )
    }
});

var Submessage = React.createClass({
    propTypes:{
        messages: React.PropTypes.array.isRequired,
    },
    getDefaultProps:function(){
        return {
            title:'默认title:',
            messages: ['默认的子消息'],
        }
    },
    render:function(){
        var msgs = [];
        this.props.messages.forEach(function(msg,index){
            msgs.push(
                <p>码农说: {msg}</p>
            )
        });

        return (
            <div>
                <h1>{this.props.title}</h1> 
                {msgs}
            </div>
        )
    }
});

ReactDOM.render( <MessageBox />, 
    document.getElementById('example')
)

上述程序中,在 MessageBox 中设置了props对象。然后,在实例化 Submessage 的时候通过 {...props}将props对象传递到子组件中,子组件获取 title 和 message 进行相应的数据展示。

4、this.props.children

上面示例中我们提到的 this.props 表示组件的属性,但是有一个例外,就是 this.props.children 属性,它表示组件的所有子节点。

// 示例6
var NotesList = React.createClass({
    render: function() {
      return (
        <ol>
          {
            React.Children.map(this.props.children, function (child) {
              return <li>{child}</li>;
            })
          }
        </ol>
      );
    }
  });

  ReactDOM.render(
    <NotesList>
      <span>hello</span>
      <span>world</span>
    </NotesList>,
    document.getElementById('example')
  );

运行结果:

这里写图片描述

我们可以看到 NoteList 组件有两个 span 子节点,它们都可以通过 this.props.children 读取。

this.props.children 的值有三种可能:

  • 如果当前组件没有子节点,它就是 undefined ;
  • 如果有一个子节点,数据类型是 object ;
  • 如果有多个子节点,数据类型就是 array

猜你喜欢

转载自blog.csdn.net/u014607184/article/details/53240660
今日推荐