在前端開發(fā)過程中,必然有些情況會(huì)需要dom元素進(jìn)行一些節(jié)點(diǎn)操作,拋開原生的獲取方法竹捉,本文將介紹React提供的解決方案态贤,本文所有示例運(yùn)行版本為react@16.11.0
1. ref
React16.3版本之后React.createRef() API付呕,使用方式如下
class Home extends Component {
constructor(props){
super(props)
this.state = {
}
// ref回調(diào)方式獲取
this.pRef = null
this.setCallBackRef = element => {
this.pRef = element
}
this.myNode = React.createRef()
this.myPara = React.createRef()
}
componentDidMount(){
console.log(this.myNode.current)
console.log(this.myPara.current)
// 無current
console.log(this.pRef)
}
render() {
return <div>
<Para ref={this.myPara} />
<p ref={this.setCallBackRef}>123</p>
<p ref={this.myNode}>{this.props.number}</p>
</div>
}
}
當(dāng) ref 被傳遞給 render 中的元素時(shí),對(duì)該節(jié)點(diǎn)的引用可以在 ref 的 current 屬性中被訪問廓八。
ref 的值根據(jù)節(jié)點(diǎn)的類型而有所不同:
- 當(dāng) ref 屬性用于 HTML 元素時(shí)锅很,構(gòu)造函數(shù)中使用 React.createRef() 創(chuàng)建的 ref 接收底層 DOM 元素作為其 current 屬性。即:
this.myNode.current
獲取到的元素為dom - 當(dāng) ref 屬性用于自定義
class
組件時(shí)多望,ref 對(duì)象接收組件的掛載實(shí)例作為其 current 屬性嫩舟。即:this.myPara.current
獲取到的是組件的實(shí)例 - 函數(shù)組件不能使用ref屬性,因?yàn)樗麄儧]有實(shí)例
備注:ref在componentDidMount
或 componentDidUpdate
生命周期鉤子觸發(fā)前更新怀偷。
可以看出家厌,我們?cè)趻煸诘阶远x組件時(shí),獲取到了這個(gè)組件的實(shí)例枢纠,可以獲取到它的props像街,context以及自定義函數(shù),那么有意思的事情就來了晋渺,我們這時(shí)可以再父組件中調(diào)用子組件的函數(shù)來完成某些業(yè)務(wù)場(chǎng)景
class Para extends React.Component {
close = () => {
alert(1)
}
render(){
return <div>
<p>1</p>
</div>
}
}
class Home extends Component {
constructor(props){
super(props)
this.myPara = React.createRef()
}
render() {
return <div>
<Para ref={this.myPara} />
<button onClick={()=>this.myPara.current.close()}>close</button>
</div>
}
}
運(yùn)行結(jié)果如下這個(gè)操作可以實(shí)現(xiàn)有趣的功能镰绎,可以好好玩一下,特別是在業(yè)務(wù)組件里木西。
2. findDOMNode()
reactDom提供了一個(gè)api畴栖,可以讓我們獲取dom節(jié)點(diǎn),不過大多數(shù)情況下不推薦使用八千,且在嚴(yán)格模式下已經(jīng)被棄用吗讶。
棄用原因:findDOMNode 只返回第一個(gè)子節(jié)點(diǎn),但是使用 Fragments恋捆,組件可以渲染多個(gè) DOM 節(jié)點(diǎn)照皆。findDOMNode 是一個(gè)只讀一次的 API。調(diào)用該方法只會(huì)返回第一次查詢的結(jié)果沸停。如果子組件渲染了不同的節(jié)點(diǎn)膜毁,則無法跟蹤此更改。因此愤钾,findDOMNode 僅在組件返回單個(gè)且不可變的 DOM 節(jié)點(diǎn)時(shí)才有效瘟滨。
class Home extends Component {
constructor(props){
super(props)
this.state = {
}
// ref回調(diào)方式獲取
this.pRef = null
this.setCallBackRef = element => {
this.pRef = element
}
this.myNode = React.createRef()
this.myPara = React.createRef()
}
// 獲取實(shí)例化組件dom
getComponent = () => {
const node = findDOMNode(this.myPara.current)
console.log(node)
}
componentDidMount(){
console.log(this.myNode.current)
console.log(this.myPara.current)
// 無current
console.log(this.pRef)
}
render() {
return <div>
<Para ref={this.myPara} />
<p ref={this.setCallBackRef}>123</p>
<p ref={this.myNode}>{this.props.number}</p>
<button onClick={()=>this.myPara.current.close()}>close</button>
<button onClick={this.getComponent}>getNode</button>
</div>
}
}
ReactDOM下的幾個(gè)api都很有趣,回頭分析一下能颁,埋個(gè)坑杂瘸。
3.useRef
react@16.8版本之后,使用hook伙菊,hook提供了useRef來獲取dom败玉,注意:返回的 ref 對(duì)象在組件的整個(gè)生命周期內(nèi)保持不變(current是變化的)敌土,相對(duì)React.createRef()在生命周期過程中是一直變化的。代碼如下
import React, { useRef, useEffect } from 'react';
import Para from './Para'
const UseRef = () => {
const myNode = useRef(null);
const myPara = useRef(null);
useEffect(() => {
console.log(myNode.current)
console.log(myPara.current)
}, []);
return <div>
<p ref={myNode}>123</p>
<Para ref={myPara} />
</div>
}
export default UseRef;