React父組件調(diào)用子組件中的方法實(shí)例詳解
文章中涉及 ref 的應(yīng)用僅為父組件調(diào)用子組件場(chǎng)景下的應(yīng)用方式,并未涵蓋 ref 的所有應(yīng)用方式!
Class組件
1. 自定義事件
Parent.js
import React, { Component } from 'react'; import Child from './Child'; class Parent extends Component { componentDidMount () { console.log(this.childRef) } handleChildEvent = (ref) => { // 將子組件的實(shí)例存到 this.childRef 中, 這樣整個(gè)父組件就能拿到 this.childRef = ref } //按鈕事件處理 handleClick = () => { // 通過(guò)子組件的實(shí)例調(diào)用組組件中的方法 this.childRef.sendMessage() } render () { return ( <> <Child onChildEvent={this.handleChildEvent} /> <button onClick={this.handleClick}>Trigger Child Event</button> </> ); } } export default Parent;
Child.js
import React, { Component } from 'react'; class Child extends Component { //子組件完成掛載時(shí), 將子組件的方法 this 作為參數(shù)傳到父組件的函數(shù)中 componentDidMount () { // 在子組件中調(diào)用父組件的方法,并把當(dāng)前的實(shí)例傳進(jìn)去 this.props.onChildEvent(this) } // 子組件的方法, 在父組件中觸發(fā) sendMessage = () => { console.log('sending message') } render () { return ( <div>Child</div> ); } } export default Child;
2. 使用 React.createRef()
ParentCmp.js
import React, { Component } from 'react'; import ChildCmp from './ChildCmp'; export default class ParentCmp extends Component { constructor(props) { super(props) // 創(chuàng)建Ref this.childRef = React.createRef() } // 按鈕事件 handleClick = () => { // 直接通過(guò) this.childRef.current 拿到子組件實(shí)例 this.childRef.current.sendMessage() } render () { return ( <> <ChildCmp ref={this.childRef} /> <button onClick={this.handleClick}>Trigger Child Event</button> </> ); } }
而子組件就是一個(gè)普通的組件
ChildCmp.js
import React, { Component } from 'react'; export default class ChildCmp extends Component { sendMessage = () => { console.log('sending message') } render () { return 'Child'; } }
3. 使用回調(diào)Refs
回調(diào) Refs 是另一種設(shè)置 Ref 的方式,它能助你更精細(xì)地控制何時(shí) refs 被設(shè)置和解除。
不同于傳遞 createRef() 創(chuàng)建的 ref 屬性,需要傳遞一個(gè)函數(shù)。
訪問(wèn) Ref 的時(shí)候也不需要 current。
ParentCmp.js
import React, { Component } from 'react'; import ChildCmp from './ChildCmp'; export default class ParentCmp extends Component { constructor(props) { super(props) // 創(chuàng)建 Ref,不通過(guò) React.createRef() this.childRef = null } // 設(shè)置 Ref setChildRef = (ref) => { this.childRef = ref } // 按鈕事件 handleClick = () => { // 直接通過(guò) this.childRef 拿到子組件實(shí)例 this.childRef.sendMessage(`Trigger Child Event from Parent`) } render () { return ( <> <ChildCmp ref={this.setChildRef} /> <button onClick={this.handleClick}>Trigger Child Event</button> </> ); } }
而子組件還是一個(gè)普通的組件
ChildCmp.js
import { Component } from 'react'; export default class ChildCmp extends Component { sendMessage = (message) => { console.log('sending message:', message) } render () { return 'Child'; } }
【注】對(duì)比自定義事件方式,回調(diào) Refs 更像是精簡(jiǎn)的自定義事件方式:
- 自定義事件名稱(chēng)變成了 ref
- 子組件內(nèi)不需要手動(dòng)綁定
Function組件
默認(rèn)情況下,不能在函數(shù)組件上使用 ref 屬性,因?yàn)樗鼈儧](méi)有實(shí)例。所以上面的兩種方式是行不通的。
解決辦法就是使用 forwardRef 和 useImperativeHandle。
不過(guò)在函數(shù)的內(nèi)部是可以使用 useRef 鉤子來(lái)獲取組件內(nèi)的 DOM 元素。
Parent.js
import React, { useRef } from 'react'; import Child from './Child'; const Parent = () => { // 通過(guò) Hooks 創(chuàng)建 Ref const childRef = useRef(null) const handleClick = () => { childRef.current.sendMessage() } return ( <> <Child ref={childRef} /> <button onClick={handleClick}>Trigger Child Event</button> </> ); } export default Parent;
Child.js
import React, { forwardRef, useImperativeHandle } from 'react'; const Child = forwardRef((props, ref) => { //將子組件的方法 暴露給父組件 useImperativeHandle(ref, () => ({ sendMessage })) const sendMessage = () => { console.log('sending message') } return ( <div>Child</div> ); }) export default Child;
注:
上面的例子中只是簡(jiǎn)單地演示了父子組件之間的方法調(diào)用,當(dāng)然實(shí)際情況中子組件中可以也會(huì)有自己的 ref 指向自己內(nèi)部的 DOM 元素,不過(guò)這些原理都是一樣的。
補(bǔ)充:子組件調(diào)用父組件方法
子組件中調(diào)用父組件的setId方法
父組件
<NavBarX item={item} current={current} getBatchDetails={(id) => this.getBatchDetails(0, id)} setId={(id, callback) => this.setState({ id }, callback)} onRef={this.onNavBarXRef} />
子組件
this.props.setId(prePageId, () => { getBatchDetails(prePageId) })
總結(jié)
到此這篇關(guān)于React父組件調(diào)用子組件中方法的文章就介紹到這了,更多相關(guān)React父組件調(diào)用子組件方法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React Native模塊之Permissions權(quán)限申請(qǐng)的實(shí)例相機(jī)
這篇文章主要介紹了React Native模塊之Permissions權(quán)限申請(qǐng)的實(shí)例相機(jī)的相關(guān)資料,希望通過(guò)本文能幫助到大家,需要的朋友可以參考下2017-09-09react開(kāi)發(fā)中如何使用require.ensure加載es6風(fēng)格的組件
本篇文章主要介紹了react開(kāi)發(fā)中如何使用require.ensure加載es6風(fēng)格的組件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05React Electron生成桌面應(yīng)用過(guò)程
這篇文章主要介紹了React+Electron快速創(chuàng)建并打包成桌面應(yīng)用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-12-12react.js實(shí)現(xiàn)頁(yè)面登錄跳轉(zhuǎn)示例
本文主要介紹了react.js實(shí)現(xiàn)頁(yè)面登錄跳轉(zhuǎn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01關(guān)于useEffect執(zhí)行兩次的問(wèn)題及解決
這篇文章主要介紹了關(guān)于useEffect執(zhí)行兩次的問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09JavaScript中的useRef 和 useState介紹
這篇文章主要給大家分享的是 JavaScript中的useRef 和 useState介紹,下列文章,我們將學(xué)習(xí) useRef 和 useState hook是什么,它們的區(qū)別以及何時(shí)使用哪個(gè)。 這篇文章中的代碼示例將僅涉及功能組件,但是大多數(shù)差異和用途涵蓋了類(lèi)和功能組件,需要的朋友可以參考一下2021-11-11React.js入門(mén)實(shí)例教程之創(chuàng)建hello world 的5種方式
React 是近期非常熱門(mén)的一個(gè)前端開(kāi)發(fā)框架。應(yīng)用非常廣泛,接下來(lái)通過(guò)本文給大家介紹React.js入門(mén)實(shí)例教程之創(chuàng)建hello world 的5種方式 ,需要的朋友參考下吧2016-05-05使用Axios在React中請(qǐng)求數(shù)據(jù)的方法詳解
這篇文章主要給大家介紹了初學(xué)React,如何規(guī)范的在react中請(qǐng)求數(shù)據(jù),主要介紹了使用axios進(jìn)行簡(jiǎn)單的數(shù)據(jù)獲取,加入狀態(tài)變量,優(yōu)化交互體驗(yàn),自定義hook進(jìn)行數(shù)據(jù)獲取和使用useReducer改造請(qǐng)求,本文主要適合于剛接觸React的初學(xué)者以及不知道如何規(guī)范的在React中獲取數(shù)據(jù)的人2023-09-09