美文网首页
react父子组件-05

react父子组件-05

作者: 逝去丶浅秋 | 来源:发表于2019-12-07 23:52 被阅读0次

    react的组件是解决html标签构建应用的不足,它的好处是能把公共的功能单独抽离成一个文件作为一个组件,哪里需要就在哪里引入。
    父子组件:组件的相互调用中,把调用者称为父组件,被调用者称为子组件。

    一、父组件向子组件传值

    在父组件引入子组件:

    import ChildComponent from './ChildComponent';
    
    1、传递值

    父组件向子组件传值,在子组件标签里设置一个属性传递,例如data:<ChildComponent data={this.state.data}/>。
    在子组件中通过this.props.data来获取,如附1代码。

    2、传递方法

    父组件向子组件传方法,在子组件标签设置一个属性传递,例如run:<ChildComponent run={this.run}/>。
    在子组件里通过this.props来调用run方法,如附1代码。

    3、传递整个组件

    将整个父组件传给子组件,在子组件标签设置一个属性传递,例如parentCpt:<ChildComponent parentCpt={this}/>。
    在子组件的方法里通过this.props.parentCpt来调用getParent,也可以调用state里的值,使用this.props.parentCpt.state,如附1代码。

    传递其他的组件:

    const Bar = <p>我是Bar组件</p>; //或
    const Bar =()=> (<p>我是Bar组件</p>);
    <ChildComponent component={Bar} /> //或
    <ChildComponent component={<Bar/>} />
    在子组件中:
    {this.props.component}获取
    
    const Bar =()=> (<p>我是Bar组件</p>);
    <ChildComponent component={()=><Bar/>} />
    传递的component是个方法,在调用时需要写成component()让其执行
    在子组件中:
    {this.props.component()}获取
    

    二、子组件向父组件传值

    1、传递值

    通过this.props.parentCpt.getChildData.bind(this,this.state.changeMsg);来把值传到父组件的getChildData方法中,来改变父组件的值,如附1代码。

    2、父组件中获取子组件的方法或值

    在父组件中的子组件标签添加ref属性:<ChildComponent ref="childCpt"/>,父组件通过this.refs来获取子组件的方法和值,见附1代码父组件中的getChildRun方法。

    三、propTypes和defaultProps

    defaultProps:父子组件传值中,如果父组件调用子组件的时候不给子组件传值,则可以在子组件中使用defaultProps定义的默认值。
    propTypes:验证父组件传值的类型合法性。

    1、defaultProps的用法

    在子组件中使用子组件名称调用defaultProps添加默认值:

    // 父子组件传值中defaultProps的用法
    ChildComponent.defaultProps={
        propsData:"父子组件传值的默认值"
    }
    

    defaultProps属性需要在组件外进行调用,写在组件(class 组件{})中会报错。
    然后子组件中使用this.props.propsData调用这个默认值。具体代码见附件1中所示。

    2、propTypes的用法

    关于propTypes更多用法可以参见React官方文档:https://zh-hans.reactjs.org/docs/typechecking-with-proptypes.html
    propTypes进行的类型检查,出于性能方面的考虑,仅在开发模式下进行检查,在JavaScript控制台将会显示警告,但是不会在页面上报错,所以开发时要看控制台中类型是否错了。需要注意的是这个检查也要写在组件外。

    ChildComponent.propTypes = {
        propsData:PropTypes.number.isRequired
    }
    

    此处的propsData是个字符串,这里检查是否为number则会报错,报错如下:

    Warning: Failed prop type: Invalid prop `propsData` of type `string` supplied to `ChildComponent`, expected `number`.
        in ChildComponent (at ParentComponent.js:43)
        in ParentComponent (at App.js:25)
        in div (at App.js:16)
        in App (at src/index.js:8)
    

    其中的isRequired为设置属性为必须传递的值。
    下面附2为可以检查的类型。
    附1:父子组件代码如下:

    import React from 'react';
    //引入子组件
    import ChildComponent from './ChildComponent';
    
    class ParentComponent extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                msg:"这是父组件",
                data:"[父组件的数据]"
            };
        }
        run=()=>{
            alert("父组件的run方法执行")
        }
        getParent=()=>{
            alert("获取到父组件未传递的方法")
        }
        getChildData=(childData)=>{
            this.setState({
                msg:childData
            })
        }
        getChildRun=()=>{
            this.refs.childCpt.run();
            this.refs.childCpt.getParentComponent();
            this.setState({
                msg:this.refs.childCpt.state.msg
            })
        }
    
        render() {
            return (
                <div>
                <hr style={{border:"1px solid"}}/>
    
                    <h2>这是父组件</h2>
                    {/* 父组件向子组件传值,在子组件标签里设置一个属性传递,例如data,通过this.state.data获取要传递的值
                        父组件向子组件传方法,在子组件标签设置一个属性传递,例如run,通过this.run获取要传递的方法
                        将整个父组件传给子组件,在子组件标签设置一个属性传递,例如parentCpt,通过this,即整个组件
                    */}
                    {/* 在子组件标签上添加ref,父组件通过this.refs来获取子组件的方法和值 */}
                    <ChildComponent ref="childCpt" data={this.state.data} run={this.run} parentCpt={this}/>
    
                    <button onClick={this.getChildRun}>父组件获取子组件的方法</button>
                    <br/><span>父组件当前msg值:{this.state.msg}</span>
    
                <hr style={{border:"1px solid"}}/>           
                </div>
            );
        }
    }
    
    export default ParentComponent;
    
    import React from 'react';
    
    class ChildComponent extends React.Component {
        constructor(props) {
            super(props);
            this.state = { 
                msg:"这是子组件",
                data:"[子组件的数据]",
                changeMsg:"changeMsg--->父组件值被改变"
             };
        }
        run=()=>{
            alert("子组件的run方法")
        }
        getParentComponent=()=>{
            this.props.parentCpt.getParent();
            alert("父组件里的msg--->"+this.props.parentCpt.state.msg);
            alert("父组件里的msg--->"+this.props.parentCpt.state.data);
        }
        render() {
            return (
                <div>
                    <hr style={{border:"1px dashed"}}/>
                    <h2>这是子组件</h2>
                    {/* 父组件向子组件传值,在子组件里通过this.props来调用data */}
                    <span>父组件向子组件传的值:{this.props.data}</span>
                    {/* 父组件向子组件传方法,在子组件里通过this.props来调用run */}
                    <button onClick={this.props.run}>点击执行父组件的run方法</button>
                    {/* 父组件向子组件传整个组件,
                        在子组件的方法里通过this.props.parentCpt来调用getParent,
                        也可以调用state里的值,使用this.props.parentCpt.state */}
                    <button onClick={this.getParentComponent}>
                            点击执行未传递的父组件的getParent方法
                   </button>
                    
                    {/* 子组件向父组件传值 */}
                    <button onClick={this.props.parentCpt.getChildData.bind(this,this.state.changeMsg)}>
                        子组件给父组件传changeMsg值
                    </button>
    
                    {/* 父子组件传值中的默认值defaultProps */}
                    <br/><span>父子组件传值中的defaultProps值:{this.props.propsData}</span>
                <hr style={{border:"1px dashed"}}/>
                </div>
                
            );
        }
    }
    
    // 父子组件传值中defaultProps的用法
    ChildComponent.defaultProps={
        propsData:"父子组件传值的默认值"
    }
    
    export default ChildComponent;
    

    附2:propTypes可检查类型:

    import PropTypes from 'prop-types';
    
    MyComponent.propTypes = {
      // 你可以将属性声明为 JS 原生类型,默认情况下
      // 这些属性都是可选的。
      optionalArray: PropTypes.array,
      optionalBool: PropTypes.bool,
      optionalFunc: PropTypes.func,
      optionalNumber: PropTypes.number,
      optionalObject: PropTypes.object,
      optionalString: PropTypes.string,
      optionalSymbol: PropTypes.symbol,
    
      // 任何可被渲染的元素(包括数字、字符串、元素或数组)
      // (或 Fragment) 也包含这些类型。
      optionalNode: PropTypes.node,
    
      // 一个 React 元素。
      optionalElement: PropTypes.element,
    
      // 一个 React 元素类型(即,MyComponent)。
      optionalElementType: PropTypes.elementType,
    
      // 你也可以声明 prop 为类的实例,这里使用
      // JS 的 instanceof 操作符。
      optionalMessage: PropTypes.instanceOf(Message),
    
      // 你可以让你的 prop 只能是特定的值,指定它为
      // 枚举类型。
      optionalEnum: PropTypes.oneOf(['News', 'Photos']),
    
      // 一个对象可以是几种类型中的任意一个类型
      optionalUnion: PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.number,
        PropTypes.instanceOf(Message)
      ]),
    
      // 可以指定一个数组由某一类型的元素组成
      optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
    
      // 可以指定一个对象由某一类型的值组成
      optionalObjectOf: PropTypes.objectOf(PropTypes.number),
    
      // 可以指定一个对象由特定的类型值组成
      optionalObjectWithShape: PropTypes.shape({
        color: PropTypes.string,
        fontSize: PropTypes.number
      }),
      
      // An object with warnings on extra properties
      //即在附加属性上带有警告的对象
      optionalObjectWithStrictShape: PropTypes.exact({
        name: PropTypes.string,
        quantity: PropTypes.number
      }),   
    
      // 你可以在任何 PropTypes 属性后面加上 `isRequired` ,确保
      // 这个 prop 没有被提供时,会打印警告信息。
      requiredFunc: PropTypes.func.isRequired,
    
      // 任意类型的数据
      requiredAny: PropTypes.any.isRequired,
    
      // 你可以指定一个自定义验证器。它在验证失败时应返回一个 Error 对象。
      // 请不要使用 `console.warn` 或抛出异常,因为这在 `onOfType` 中不会起作用。
      customProp: function(props, propName, componentName) {
        if (!/matchme/.test(props[propName])) {
          return new Error(
            'Invalid prop `' + propName + '` supplied to' +
            ' `' + componentName + '`. Validation failed.'
          );
        }
      },
    
      // 你也可以提供一个自定义的 `arrayOf` 或 `objectOf` 验证器。
      // 它应该在验证失败时返回一个 Error 对象。
      // 验证器将验证数组或对象中的每个值。验证器的前两个参数
      // 第一个是数组或对象本身
      // 第二个是他们当前的键。
      customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
        if (!/matchme/.test(propValue[key])) {
          return new Error(
            'Invalid prop `' + propFullName + '` supplied to' +
            ' `' + componentName + '`. Validation failed.'
          );
        }
      })
    };
    

    写在最后:

    • 如果文章中有错误或是表达不准确的地方,欢迎大家评论中指正,以便我完善。
    • 文章我也会根据所学到新的知识不断更新。

    相关文章

      网友评论

          本文标题:react父子组件-05

          本文链接:https://www.haomeiwen.com/subject/brfjgctx.html