網(wǎng)站首頁 編程語言 正文
文章中涉及 ref 的應(yīng)用僅為父組件調(diào)用子組件場景下的應(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) => {
// 將子組件的實例存到 this.childRef 中, 這樣整個父組件就能拿到
this.childRef = ref
}
//按鈕事件處理
handleClick = () => {
// 通過子組件的實例調(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 {
//子組件完成掛載時, 將子組件的方法 this 作為參數(shù)傳到父組件的函數(shù)中
componentDidMount () {
// 在子組件中調(diào)用父組件的方法,并把當(dāng)前的實例傳進(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 = () => {
// 直接通過 this.childRef.current 拿到子組件實例
this.childRef.current.sendMessage()
}
render () {
return (
<>
<ChildCmp ref={this.childRef} />
<button onClick={this.handleClick}>Trigger Child Event</button>
</>
);
}
}
而子組件就是一個普通的組件
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ì)地控制何時 refs 被設(shè)置和解除。
不同于傳遞 createRef() 創(chuàng)建的 ref 屬性,需要傳遞一個函數(shù)。
訪問 Ref 的時候也不需要 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,不通過 React.createRef()
this.childRef = null
}
// 設(shè)置 Ref
setChildRef = (ref) => {
this.childRef = ref
}
// 按鈕事件
handleClick = () => {
// 直接通過 this.childRef 拿到子組件實例
this.childRef.sendMessage(`Trigger Child Event from Parent`)
}
render () {
return (
<>
<ChildCmp ref={this.setChildRef} />
<button onClick={this.handleClick}>Trigger Child Event</button>
</>
);
}
}
而子組件還是一個普通的組件
ChildCmp.js
import { Component } from 'react';
export default class ChildCmp extends Component {
sendMessage = (message) => {
console.log('sending message:', message)
}
render () {
return 'Child';
}
}
【注】對比自定義事件方式,回調(diào) Refs 更像是精簡的自定義事件方式:
- 自定義事件名稱變成了 ref
- 子組件內(nèi)不需要手動綁定
Function組件
默認(rèn)情況下,不能在函數(shù)組件上使用 ref 屬性,因為它們沒有實例。所以上面的兩種方式是行不通的。
解決辦法就是使用 forwardRef 和 useImperativeHandle。
不過在函數(shù)的內(nèi)部是可以使用 useRef 鉤子來獲取組件內(nèi)的 DOM 元素。
Parent.js
import React, { useRef } from 'react';
import Child from './Child';
const Parent = () => {
// 通過 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;
注:
上面的例子中只是簡單地演示了父子組件之間的方法調(diào)用,當(dāng)然實際情況中子組件中可以也會有自己的 ref 指向自己內(nèi)部的 DOM 元素,不過這些原理都是一樣的。
補充:子組件調(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é)
原文鏈接:https://blog.csdn.net/qq_40738077/article/details/119427313
相關(guān)推薦
- 2022-11-07 go?分布式鎖簡單實現(xiàn)實例詳解_Golang
- 2022-07-27 關(guān)于pytest結(jié)合csv模塊實現(xiàn)csv格式的數(shù)據(jù)驅(qū)動問題_python
- 2022-05-09 Docker?Overlay2磁盤空間占用過大清理的方法實現(xiàn)_docker
- 2022-02-22 使用Flex布局實現(xiàn)頭部固定,內(nèi)容區(qū)域滾動
- 2023-02-06 Python利用Pytorch實現(xiàn)繪制ROC與PR曲線圖_python
- 2022-10-03 Observing?KVO?Key-Value基本使用原理示例詳解_IOS
- 2022-04-12 .NET 6 “目標(biāo)進(jìn)程已退出,但未引發(fā) CoreCLR 啟動事件。請確保將目標(biāo)進(jìn)程配置為使用 .N
- 2022-05-22 C#多線程編程Task用法詳解_C#教程
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支