React父子组件的传参

4,052 阅读5分钟

父组件传递子组件

属性(props)传递

属性(props)传递: 调取子组件的时候,把信息基于属性的方式传递给子组件(子组件Props中存储传递的信息);这种方式只能父组件把信息传递子组件,子组件无法直接的把信息传递给父组件,也就是属性传递(是单向传递的);

父到子(分两步)

父组件要做的事情

1.给父组件调用组件的的地方传参

<Child count={ {n:this.state.n,m:this.state.m} } />
子组件要做的事情

2.子组件需要

1.继承父组件的props属性
    constructor(props){
        super(props);
        console.log(this.props);
    }
2. 给需要用的的地方赋值
    <div>m的值: { this.props.count.m }</div>

子到父(基于回调函数=>父组件把一个函数传递给子组件,也就是子组件执行了父组件的方法,还可以传递过去一些值,想把父组件的值改成啥就是啥)

父组件做的事
1. 定义一个函数
updateChange = (m)=>{
    this.setState({
        m: m
    })
}
2. 调用子组件的地方传递
<Child 
    count={ {n:this.state.n,m:this.state.m} }
    updateChange={ updateChange }
/>

代码

子组件做的事情
在要改变父组件状态的地方执行父组件传递进来的函数
<button onClick={()=>{
    this.props.updateChange(6);
}}>改变m的值</button>
父组件
import React,{ Component } from 'react'
import PropTypes from 'prop-types'
import Child from './Child.js'
export default class parent extends Component{
    constructor(){
        super();
        this.state = {
            n : 10,
            m : 10
        }
    }
    
    updateChange = (m)=>{
        this.setState({
            m: m
        })
    }
    
    
    render(){
        return(
            <div>
                <div>n的值: { this.state.n } </div>
                <div>m的值: { this.state.m }</div>
                <Child 
                    count={ {n:this.state.n,m:this.state.m} }
                    updateChange={ updateChange }
                />
            </div>
        )
    }
}
子组件
import React,{ Component } from 'react'
import Grandson from './Grandson.js'

export default class Child extends Component{
    constructor(props){
        super(props);
        console.log(this.props);
    }
    render(){
        return(
            <div>
                <div>n的值: { this.props.count.n } </div>
                <div>m的值: { this.props.count.m }</div>
                <button onClick={()=>{
                    this.props.updateChange(6);
                }}>改变m的值</button>
                <Grandson count={ {n: this.props.count.n ,m:this.props.count.m } } />
            </div>
        )
    }
}
孙组件
import React,{ Component } from 'react'
export default class Grandson extends Component{
    constructor(props,context){
        super(props,context);
    }
    render(){
        return(
            <div>
                <div>n的值: { this.props.count.n } </div>
                <div>m的值: { this.props.count.m }</div>
            </div>
        )
    }
}

上下文(context)传递

上下文传递: 父组件先把需要给后代元素(包括孙子元素)使用的信息都设置好(设置在上下文中),后代组件需要用到父组件用到中的信息,主动去父组件中调取使用即可.

父到子传参(分三步)

父组件要做的事情

// 1.设置上下文中信息的类型 static childContextTypes = { n: PropTypes.number, m: PropTypes.number }

// 2.获取子组件的上下文 getChildContext(){ // -> return的是啥,相当于给子组件上下文设置成啥. let { n,m } = this.state; return { n, m } }

子组件要做的事情

// 3. 首先类型需要和设置时候的类型一样,否则报错,并且你需要用啥,就写啥即可. static contextTypes = {

n: PropTypes.number,
m: PropTypes.number

}

子到父(基于回调函数=>父组件把一个函数传递给子组件,也就是子组件执行了父组件的方法,还可以传递过去一些值,想把父组件的值改成啥就是啥)

代码

父组件
import React,{ Component } from 'react'
import PropTypes from 'prop-types'
import Child from './Child.js'
export default class parent extends Component{
    constructor(props){
        super(props);
        this.state = {
            n : 10,
            m : 10
        }
    }
    
    // 分三步
    // 1.设置上下文中信息的类型
    static childContextTypes = {
        n: PropTypes.number,
        m: PropTypes.number,
        callback: PropTypes.func
    }
    // 2.获取子组件的上下文
    getChildContext(){
        // 只要render重新渲染,就会执行这个方法,重新更新父组件的上下文信息,如果父组件上下文信息更改了,子组件在重新调取的时候,会使用最新的上下文信息(render=>context=>子组件调取渲染);
        let { n,m } =this.state
        return{
            n,
            m,
            callback
        }
    }
    
    // 1. 子改变父的定义的函数
    updateChange = (n)=> {
        this.setState({
            n: n
        })
    }
    
    
    render(){
        return(
            <div>
                <div>n的值: { this.state.n } </div>
                <div>m的值: { this.state.m }</div>
                <Child />
            </div>
        )
    }
}
子组件
import React,{ Component } from 'react'
import PropTypes from 'prop-types'
import Grandson from './Grandson.js'
export default class Child extends Component{
    constructor(props,context){
        super(props,context);
        context.n = 1000;   // 是可以修改context的值
    }
    
    // 3.首先类型需要和设置时候的类型一样,否则报错,并且你需要用啥,就写啥即可.
    static contextTypes = {
        n: PropTypes.number,
        m: PropTypes.number,
        callback: PropTypes.func
    }
    
    // 给孙组件
    /*
    static childContextTypes = {
        n: PropTypes.number,
        m: PropTypes.number,
    }
    getChildContext(){
        // -> return的是啥,相当于给子组件上下文设置成啥.
        let  { n, m } = this.context
        return {
            n,
            m
        }
    }
    */
    
    render(){
        return(
            <div>
                <div>n的值: { this.context.n } </div>
                <div>m的值: { this.context.m }</div>
                {/* 2.子改变父的执行 */}
                <button onClick={ ()=>{  
                    let n = this.context.n+1
                    this.context.callback(n)  
                }>改变n的值</button>
                <Grandson />
            </div>
        )
    }
}
##### 孙组件
```javascript
import React,{ Component } from 'react'
import PropTypes from 'prop-types'
export default class Grandson extends Component{
    constructor(props,context){
        super(props,context);
        console.log(this.context);
    }
    
    static contextTypes = {
        n: PropTypes.number,
        m: PropTypes.number,
    }
    
    render(){
        return(
            <div>
                <div>n的值: { this.context.n } </div>
                <div>m的值: { this.context.m }</div>
            </div>
        )
    }
}

属性传递和上下文传递的区别

属性传递: 
    1. 操作起来简单;
    2. 子组件被动接收传递的值(组件内的属性是,子组件是不允许修改的(只读的));
    3. 只能父传子(子传父不行,父传孙也需要处理,需要子组件处理传递给孙组件).
上下文传递:
    1. 操作起来相对复杂一些;
    2. 子组件主动接受传递的值(组件内的context(上下文),子组件是可以修改context的值,但是不会影响父组件的值);
    3. 一旦设置了父组件的上下文信息,其后代组件都可以拿来用,不需要一层层传递下去.

细节之处,略有疏漏,如有不足或者错误的地方,欢迎大佬批评并加以指正.谢谢.