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节点

 <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

React Native中ref的用法(通过组件的ref属性,来获取真实的组件)的更多相关文章

  1. react native中state和ref的使用

    react native中state和ref的使用 因props是只读的,页面中需要交互的情况我们就需要用到state. 一.如何使用state 1:初始化state 第一种方式: construct ...

  2. React Native中加载指示器组件ActivityIndicator使用方法

    这里讲一下React Native中的一个组件——ActivityIndicator,这是一个加载指示器,俗称菊花,很常见的,效果如下所示: 可以看到图中有两个加载指示器,一大一小,这是尺寸不是我设置 ...

  3. React Native中组件的props和state

    一.组件的属性(props)和状态(state) 1.属性(props) 它是组件的不可变属性(组件自己不可以自己修改props). 组件自身定义了一组props作为对外提供的接口,展示一个组件时只需 ...

  4. [转] 「指尖上的魔法」 - 谈谈 React Native 中的手势

    http://gold.xitu.io/entry/55fa202960b28497519db23f React-Native是一款由Facebook开发并开源的框架,主要卖点是使用JavaScrip ...

  5. 在 React Native 中使用 Redux 架构

    前言 Redux 架构是 Flux 架构的一个变形,相对于 Flux,Redux 的复杂性相对较低,而且最为巧妙的是 React 应用可以看成由一个根组件连接着许多大大小小的组件的应用,Redux 也 ...

  6. [转] 在React Native中使用ART

    http://bbs.reactnative.cn/topic/306/%E5%9C%A8react-native%E4%B8%AD%E4%BD%BF%E7%94%A8art 前半个月捣腾了一下Rea ...

  7. react native中使用echarts

    开发平台:mac pro node版本:v8.11.2 npm版本:6.4.1 react-native版本:0.57.8 native-echarts版本:^0.5.0 目标平台:android端收 ...

  8. 在React Native中,使用fetch网络请求 实现get 和 post

    //在React Native中,使用fetch实现网络请求 /* fetch 是一个封装程度更高的网络API, 使用了Promise * Promise 是异步编程的一种解决方案 * Promise ...

  9. 《React Native 精解与实战》书籍连载「React Native 中的生命周期」

    此文是我的出版书籍<React Native 精解与实战>连载分享,此书由机械工业出版社出版,书中详解了 React Native 框架底层原理.React Native 组件布局.组件与 ...

随机推荐

  1. index首页加载数据库数据方法

    https://blog.csdn.net/qq_33198758/article/details/82987805 在做网站的时候,会遇到需要首页加载数据库数据的情况.而web.xml配置的首页: ...

  2. Python文件查找

    #!/usr/bin/python   import os import string   def get_name(path_name, file_str):         dir_name = ...

  3. Python3-json3csv

    import json import csv json_str = '[{"a":1,"b":"2","c":" ...

  4. springboot与springcloud版本不对应导致报错java.lang.NoSuchMethodError: org.springframework.boot.builder.SpringApplicationBuilder.<init>([Ljava/lang/Object;)V

    springboot启动报错: 10:31:50.221 [main] ERROR org.springframework.boot.SpringApplication - Application r ...

  5. numpy常用矩阵操作

    1.删除列 column_to_delete = [0, 1, 2] arr = np.delete(arr, [0, 1, 2], axis=1) 2.归一化 arr = normalize(arr ...

  6. java——通过GenericObjectPool获取到的资源,调用close()方法会close还是returnObject?

    一种优雅的关闭资源的方式是使用try(){}cache(){} 就像这样: 这时候,try()里面的资源会在return语句执行结束之后自动调用close()方法,那么问题来了,当我们使用连接池的时候 ...

  7. C# dll文件添加引用失败

    未能添加对“***/***.dll”的引用.请确保此文件可访问并且是一个有效的程序集或 COM 组件. 原因:dll文件使用其他语言生成,C#无法识别 解决方法: 添加using System.Run ...

  8. MySQL 临时修改全局变量

    1.查询全局变量: SHOW GLOBAL VARIABLES [LIKE '%search key%']; 2.修改全局变量: SET GLOBAL auto_increment_increment ...

  9. js的DOM操作整理(整理)

    js的DOM操作整理(整理) 一.总结 一句话总结: dom操作有用原生js的dom操作,也可以用对js封装过的jquery等插件来更加方便的进行dom操作 1.dom是什么? 对于JavaScrip ...

  10. hdu 5791 Two 二维dp

    Two Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submiss ...