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