React:Component类型的父子组件如何传参?我来告诉你!

743 阅读6分钟

@TOC

父子组件关系简谈

父组件 内 包含有 子组件,这是基本关系

所以,父组件render渲染时,子组件会紧紧跟随伴其渲染,无论何种情况都会(例如父组件自己setState,子组件也会跟着重新render)。

ref属性

下图是16.x以后React新的生命周期图,其实按使用频率来看没什么必要在意,我们平常也就用ComponentDidMount()多一些。这个函数会在一个组件渲染完成后“必定执行”,所以你想在组件渲染完后干些什么其他的操作可以在这里自由DIY。 不过关于生命周期这里有个重要的点需要注意:不要在ComponentDidMount()里面执行this.setState()函数!每次setState都会强制重新渲染组件,而重新渲染又必然重新执行一次ComponentDidMount(),禁止套娃!!! 在这里插入图片描述 了解如上基本情况后就可以上手写写代码了

父组件调用子组件函数

目标:在父组件里调用子组件的一个函数 我使用的方法:ref与onRef。因为实际上可以为多个孩子创建好关联,所以我一般都是使用这种方法的

下面我用react脚手架的App.js作为父组件进行演示

App.js

import React, { Component } from 'react'
import Child1 from './component/Child1'

export default class App extends Component {
    // react的onRef会自动检查从哪个名字的组件进来执行的onRef
    onRef (name, ref) {
        switch (name) {
            case 'Child1':
                this.Child1 = ref
                break
            default:
                break
        }
    }
    // 调用子组件Child1的一个函数
    // 其实子组件里那个函数随便起名,但为了做工程,代码命名统一一些,这里都叫func1
    func1 = () => {
        console.log("父组件调用child1")
        this.Child1.func1()
    }
	// 关于如何、何时调用func1,自己具体项目具体分析,这里为了演示,就简单采用Button的onClick触发来展示一下
    render() {
        return (
        	<div>
        		<button onClick={this.func1}>
					<Child1 onRef={this.onRef.bind(this)}/>
				</button>
        	</div>
        )
    }
}

Child1.js

import React, { Component } from 'react'

export default class Child1 extends Component {
    // 渲染后和父组件的ref: Child1建立关联,使父组件调用Child1时直接使用的就是子组件Child1对象
    componentDidMount = () => {
        this.props.onRef('Child1', this)
    }
    func1 = () => {
        console.log("我雀实是Child1")
    }

    render() {
        return (
            <div>
                我是Child1
            </div>
        )
    }
}

点击按钮 1,效果如图: 在这里插入图片描述

父组件调用子组件函数且传参

目标:在父组件里调用子组件的一个函数,并且由父组件传参数给子组件函数(非props)

那么我接下来继续在上文的基础上增加一个child2:

App.js

import React, {Component} from 'react'
import Child1 from './component/Child1'
import Child2 from './component/Child2'

export default class App extends Component {
    // react的onRef会自动检查从哪个名字的组件进来执行的onRef
    onRef (name, ref) {
        switch (name) {
            case 'Child1':
                this.Child1 = ref
                break
            case 'Child2':
                this.Child2 = ref
                break
            default:
                break
        }
    }
    // 调用子组件Child1的一个函数
    // 其实子组件里那个函数随便起名,但为了做工程,代码命名统一一些,这里都叫func1
    func1 = () => {
        console.log("父组件调用child1")
        this.Child1.func1()
    }
    func2 = (param1, param2) => {
        console.log("父组件调用child2")
        this.Child2.func2(param1, param2)
    }
	// 关于如何、何时调用func1,func2,自己具体项目具体分析,这里为了演示,就简单采用Button的onClick触发来展示一下
    render() {
        return (
        	<div>
        		<button onClick={this.func1}>
					<Child1 onRef={this.onRef.bind(this)}/>
				</button><br/>
                {/* 使用bind函数,绑定App对象后,附加上自己想传的各个参数 */}
				<button onClick={this.func2.bind(this, "参数1", "参数2")}>
					<Child2 onRef={this.onRef.bind(this)}/>
        		</button>
        	</div>
        )
    }
}

Child2.js

import React, { Component } from 'react'

export default class Child1 extends Component {
    componentDidMount = () => {
        this.props.onRef('Child2', this)
    }
    func2 = (param1, param2) => {
        console.log("我真的是Child2",param1, param2)
    }

    render() {
        return (
            <div>
                我是Child2
            </div>
        )
    }
}

点击按钮 2,效果如图: 在这里插入图片描述

子组件调用父组件函数

目标:子组件调用父组件的一个函数

重要应用:子组件可通过这种形式向父组件传参

使用ref的话只能简单得让子组件“为父所用”,所以这里可以使用神奇的“props”参数,直接把一个函数传给子组件。这样,父组件定义的东西就相当于送给子组件使用了

App.js

import React, {Component} from 'react'
import Child1 from './component/Child1'

export default class App extends Component {

    funcFather1 = () =>{
        console.log("Child1调用本爹了")
    }
	// 关于如何、何时调用func1,func2,自己具体项目具体分析,这里为了演示,就简单采用Button的onClick触发来展示一下
    render() {
        return (
        	<div>
                <Child1 funcFather1={this.funcFather1}/>
        	</div>
        )
    }
}

Child1.js

import React, { Component } from 'react'

export default class Child1 extends Component {
    // 渲染后和父组件的ref: Child1建立关联,使父组件调用Child1时直接使用的就是子组件Child1对象
    componentDidMount = () => {
        this.props.onRef('Child1', this)
    }
    func1 = () => {
        console.log("我雀实是Child1")
    }

    render() {
        return (
            <div>
                我是Child1<br/>
                <button onClick={this.props.funcFather1}>
                    Child1要调用他爹
                </button>
            </div>
        )
    }
}

点击div内按钮,效果如图: 在这里插入图片描述

子组件调用父组件函数且传参

在使用props后其实子组件向父组件传参就很简单了,直接传!

App.js

import React, {Component} from 'react'
import Child1 from './component/Child1'
import Child2 from './component/Child2'

export default class App extends Component {

    funcFather1 = () =>{
        console.log("Child1调用本爹了")
    }
    funcFather2 = (param1, param2) =>{
        console.log("Child2调用本爹了", param1, param2)
    }
	// 关于如何、何时调用func1,func2,自己具体项目具体分析,这里为了演示,就简单采用Button的onClick触发来展示一下
    render() {
        return (
        	<div>
                <Child1 funcFather1={this.funcFather1}/>
                <Child2 funcFather2={this.funcFather2}/>
        	</div>
        )
    }
}

Child2.js

import React, { Component } from 'react'

export default class Child1 extends Component {

    render() {
        return (
            <div>
                我是Child2<br/>
                <button onClick={this.props.funcFather2("欸嘿", "欸嘿囊带优")}>
                    Child2要调用他爹
                </button>
            </div>
        )
    }
}

点击div内按钮 2,效果如图: 在这里插入图片描述 歪日,,点击了一点用也没有,但渲染时却执行了 原因分析: 由于在Child2的button onClick属性中我们写的是.funcFather2()这种带括号形式,而非.funcFather2,渲染时这个函数成为了直接执行的一段代码,而非被作为onClick触发的函数 解决办法: 在Child2定义新函数用来实现触发

Child2.js(改进)

import React, { Component } from 'react'

export default class Child1 extends Component {

    funcFather2 = () => {
        // 调用参数内的funcFather2
        this.props.funcFather2("欸嘿", "欸嘿囊带优")
    }

    render() {
        return (
            <div>
                我是Child2<br/>
                {/* 这一次调用的是child2对象自己的funcFather2 */}
                <button onClick={this.funcFather2}>
                    Child2要调用他爹
                </button>
            </div>
        )
    }
}

点击div内按钮 2,效果如图: 在这里插入图片描述歪日,,渲染时又默认执行了??? 解决办法: 在Child2定义以箭头函数触发

Child2.js(最终版)

import React, { Component } from 'react'

export default class Child1 extends Component {

    funcFather2 = (param1, param2) => {
        // 调用参数内的funcFather2
        this.props.funcFather2(param1, param2)
    }

    render() {
        return (
            <div>
                我是Child2<br/>
                {/* 这一次调用的是child2对象自己的funcFather2 */}
                <button onClick={()=>this.funcFather2("欸嘿", "欸嘿囊带优")}>
                    Child2要调用他爹
                </button>
            </div>
        )
    }
}

点击div内按钮 2,终于正常了,效果如图: 在这里插入图片描述

Route子组件调用父组件函数

Router中,组件的关系虽然和普通的差不多但是调用方式有所不同。 我选择的方法是直接在Route内调用render,把父组件函数传给子组件

App.js

import React, {Component} from 'react'
import Child1 from './component/Child1'
import { Route } from 'react-router-dom';

export default class App extends Component {

    funcFather1 = () =>{
        console.log("Child1调用本爹了")
    }
    render() {
        return (
        	<div>
                father
                <Route path="/child1/" render={()=><Child1 funcFather1={this.funcFather1}/>} ></Route>
        	</div>
        )
    }
}

Child1.js

import React, { Component } from 'react'

export default class Child1 extends Component {

    render() {
        return (
            <div>
                <button onClick={this.props.funcFather1}>
                    Child1要调用
                </button>
            </div>
        )
    }
}

在Child页面点击按钮,效果如图: 在这里插入图片描述 补充一下我的项目框架,组件全放在component里了在这里插入图片描述