React的ref有3種用法:
1. 字串(已廢棄)
2. 回撥函式
3. React.createRef() (React16.3提供)
1. 字串
最早的ref用法。
1.dom節點上使用,通過this.refs[refName]來引用真實的dom節點
<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節點上使用回撥函式
<input ref={(input) => {this.textInput = input;}} type="text" />
2.類元件上使用
<CustomInput ref={(input) => {this.textInput = input;}} />
3.可用通過props跨級傳遞的方式來獲取子孫級dom節點或元件例項
下面是在跨兩級獲取到孫級別的元件內部的dom節點
function CustomTextInput(props) { return ( <div> <input ref={props.inputRef} /> </div> ); } function Parent(props) { return ( <div> My input: <CustomTextInput inputRef={props.inputRef} /> </div> ); } class Grandparent extends React.Component { render() { return ( <Parent inputRef={el => this.inputElement = el} \/> ); } }
3.React.createRef()
在React 16.3版本後,使用此方法來建立ref。將其賦值給一個變數,通過ref掛載在dom節點或元件上,該ref的current屬性
將能拿到dom節點或元件的例項
例如:
class Child extends React.Component{ constructor(props){ super(props); this.myRef=React.createRef(); } componentDidMount(){ console.log(this.myRef.current); } render(){ return <input ref={this.myRef}/> } }
4.React.forwardRef
同樣是React 16.3版本後提供的,可以用來建立子元件,以傳遞ref。
例如:
//子元件(通過forwardRef方法建立) const Child=React.forwardRef((props,ref)=>( <input ref={ref} /> )); //父元件 class Father extends React.Component{ constructor(props){ super(props); this.myRef=React.createRef(); } componentDidMount(){ console.log(this.myRef.current); } render(){ return <Child ref={this.myRef}/> } }
子元件通過React.forwardRef來建立,可以將ref傳遞到內部的節點或元件,進而實現跨層級的引用。
forwardRef在高階元件中可以獲取到原始元件的例項。
例如:
//生成高階元件 const logProps=logProps(Child); //呼叫高階元件 class Father extends React.Component{ constructor(props){ super(props); this.myRef=React.createRef(); } componentDidMount(){ console.log(this.myRef.current); } render(){ return <LogProps ref={this.myRef}/> } } //HOC function logProps(Component) { class LogProps extends React.Component { componentDidUpdate(prevProps) { console.log('old props:', prevProps); console.log('new props:', this.props); } render() { const {forwardedRef, ...rest} = this.props; // Assign the custom prop "forwardedRef" as a ref return <Component ref={forwardedRef} {...rest} />; } } // Note the second param "ref" provided by React.forwardRef. // We can pass it along to LogProps as a regular prop, e.g. "forwardedRef" // And it can then be attached to the Component. return React.forwardRef((props, ref) => { return <LogProps {...props} forwardedRef={ref} />; }); }
//生成高階元件 const logProps=logProps(Child); //呼叫高階元件 class Father extends React.Component{ constructor(props){ super(props); this.myRef=React.createRef(); } componentDidMount(){ console.log(this.myRef.current); } render(){ return <LogProps ref={this.myRef}/> } } //HOC function logProps(Component) { class LogProps extends React.Component { componentDidUpdate(prevProps) { console.log('old props:', prevProps); console.log('new props:', this.props); } render() { const {forwardedRef, ...rest} = this.props; // Assign the custom prop "forwardedRef" as a ref return <Component ref={forwardedRef} {...rest} />; } } // Note the second param "ref" provided by React.forwardRef. // We can pass it along to LogProps as a regular prop, e.g. "forwardedRef" // And it can then be attached to the Component. return React.forwardRef((props, ref) => { return <LogProps {...props} forwardedRef={ref} />; }); }
注意:
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