ref是什么?
ref是組件的特殊屬性,組件被渲染后,指向組件的一個引用。可以通過組件的ref屬性,來獲取真實的組件。因為,組件並不是真正的DOM節點,而是存在於內存中的一種數據結構,
稱為虛擬的DOM,只有當它真正的插入文檔之后,才變為真正的DOM節點。根據React的設計,所以的DOM變動都發生在虛擬DOM上,然后再將實際的部分反映到真實的DOM上--這就是 DOM DIff,它可以提高頁面性能。 如何使用ref呢? ref屬性的定義是在使用組件的部分,而組件的方法之類的都是在定義組件的里面就有的。render方法被調用的時候,組件就會被渲染。渲染完成之后,就可以獲取這個組件實例啦,因而就可以調用組件實例里的方法或者變量啦。
React的ref有3種用法:
1. 字符串(已廢棄)
2. 回調函數
3. React.createRef() (React16.3提供)
1. 字符串
最早的ref用法。
1.dom節點上使用,通過this.refs[refName]來引用真實的dom節點
1 <input ref="inputRef" /> //this.refs['inputRef']來訪問
2.類組件上使用,通過this.refs[refName]來引用組件的實例
<CustomInput ref="comRef" /> //this.refs['comRef']來訪問
2. 回調函數
回調函數就是在dom節點或組件上掛載函數,函數的入參是dom節點或組件實例,達到的效果與字符串形式是一樣的,
都是獲取其引用。
回調函數的觸發時機:。
1. 組件渲染后,即componentDidMount后
2. 組件卸載后,即componentWillMount后,此時,入參為null
3. ref改變后
1.dom節點上使用回調函數
1 <input ref={(input) => {this.textInput = input;}} type="text" />
2.類組件上使用使用回調函數
1 <CustomInput ref={(input) => {this.textInput = input;}} />
3.可用通過props跨級傳遞的方式來獲取子孫級dom節點或組件實例
下面是在跨兩級獲取到孫級別的組件內部的dom節點
1 function CustomTextInput(props) { 2 return ( 3 <div> 4 <input ref={props.inputRef} /> 5 </div> 6 ); 7 } 8 function Parent(props) { 9 return ( 10 <div> 11 My input: <CustomTextInput inputRef={props.inputRef} /> 12 </div> 13 ); 14 } 15 class Grandparent extends React.Component { 16 render() { 17 return ( 18 <Parent 19 inputRef={el => this.inputElement = el} 20 \/> 21 ); 22 } 23 }
3.React.createRef()
在React 16.3版本后,使用此方法來創建ref。將其賦值給一個變量,通過ref掛載在dom節點或組件上,該ref的current屬性
將能拿到dom節點或組件的實例
例如
1 class Child extends React.Component{ 2 constructor(props){ 3 super(props); 4 this.myRef=React.createRef(); 5 } 6 componentDidMount(){ 7 console.log(this.myRef.current); 8 } 9 render(){ 10 return <input ref={this.myRef}/> 11 } 12 }
4.React.forwardRef
同樣是React 16.3版本后提供的,可以用來創建子組件,以傳遞ref。
例如:
1 //子組件(通過forwardRef方法創建) 2 const Child=React.forwardRef((props,ref)=>( 3 <input ref={ref} /> 4 )); 5 6 //父組件 7 class Father extends React.Component{ 8 constructor(props){ 9 super(props); 10 this.myRef=React.createRef(); 11 } 12 componentDidMount(){ 13 console.log(this.myRef.current); 14 } 15 render(){ 16 return <Child ref={this.myRef}/> 17 } 18 }
子組件通過React.forwardRef來創建,可以將ref傳遞到內部的節點或組件,進而實現跨層級的引用。
forwardRef在高階組件中可以獲取到原始組件的實例
例如:
1 //生成高階組件 2 const logProps=logProps(Child); 3 4 //調用高階組件 5 class Father extends React.Component{ 6 constructor(props){ 7 super(props); 8 this.myRef=React.createRef(); 9 } 10 componentDidMount(){ 11 console.log(this.myRef.current); 12 } 13 render(){ 14 return <LogProps ref={this.myRef}/> 15 } 16 } 17 18 //HOC 19 function logProps(Component) { 20 class LogProps extends React.Component { 21 componentDidUpdate(prevProps) { 22 console.log('old props:', prevProps); 23 console.log('new props:', this.props); 24 } 25 26 render() { 27 const {forwardedRef, ...rest} = this.props; 28 29 // Assign the custom prop "forwardedRef" as a ref 30 return <Component ref={forwardedRef} {...rest} />; 31 } 32 } 33 34 // Note the second param "ref" provided by React.forwardRef. 35 // We can pass it along to LogProps as a regular prop, e.g. "forwardedRef" 36 // And it can then be attached to the Component. 37 return React.forwardRef((props, ref) => { 38 return <LogProps {...props} forwardedRef={ref} />; 39 }); 40 }
1 //生成高階組件 2 const logProps=logProps(Child); 3 4 //調用高階組件 5 class Father extends React.Component{ 6 constructor(props){ 7 super(props); 8 this.myRef=React.createRef(); 9 } 10 componentDidMount(){ 11 console.log(this.myRef.current); 12 } 13 render(){ 14 return <LogProps ref={this.myRef}/> 15 } 16 } 17 18 //HOC 19 function logProps(Component) { 20 class LogProps extends React.Component { 21 componentDidUpdate(prevProps) { 22 console.log('old props:', prevProps); 23 console.log('new props:', this.props); 24 } 25 26 render() { 27 const {forwardedRef, ...rest} = this.props; 28 29 // Assign the custom prop "forwardedRef" as a ref 30 return <Component ref={forwardedRef} {...rest} />; 31 } 32 } 33 34 // Note the second param "ref" provided by React.forwardRef. 35 // We can pass it along to LogProps as a regular prop, e.g. "forwardedRef" 36 // And it can then be attached to the Component. 37 return React.forwardRef((props, ref) => { 38 return <LogProps {...props} forwardedRef={ref} />; 39 }); 40 }
注意:
1. ref在函數式組件上不可使用,函數式組件無實例,但是其內部的dom節點和類組件可以使用
2. 可以通過ReactDOM.findDOMNode(),入參是一個組件或dom節點,返回值的組件對應的dom根節點或dom節點本身
通過refs獲取到組件實例后,可以通過此方法來獲取其對應的dom節點
3. React的render函數返回的是vDom(虛擬dom)
參考:https://blog.csdn.net/liangklfang/article/details/72858295
https://blog.csdn.net/liwusen/article/details/80009968
