ref的三种使用方式与forwardRef
ref的功能
场景:有一个class类组件,通过ref获取子组件实例或者DOM节点,进行手动操作,而不仅仅是props更新来更新节点。
获取节点自己做一些绑定或其他操作。
(当然除此之外可以querySelect,document.querySelector("#demo");
querySelector() 方法返回文档中匹配指定 CSS 选择器的一个元素。)
一、ref的三种使用方式
- 源码前言
function Component (props, context,updater)
Component.prototype.setState = function(partialState,callback) {
…
this.updater.enqueueSetState(this,partialState,callback,)
}
updater.enqueueSetState是在reactDOM里实现的。
Component 核心是一样的,
更新的流程不同
类的继承中初始化定义函数的时候,在他的原型上还可以使用传递进来的参数吗?源码上是可以的,回家试一试。
- React中ref的三种使用方式:
应用:
1.this.refs.stringRef.textContent = "string ref got"
2.this.methodRef.textContent = "method ref got"
3.//先创建一个ref对象
export default class Comp extends React.Component {
super();
this.objRef = React.createRef();
}
//
this.objRef.current.textContent = "obj ref got"
<p ref = {this.objRef}>asdf</p>
//string ref 想要获取的那个节点的props上面使用ref属性传入一个字符串,
react在完成这个节点的渲染之后,会在this.ref上面挂载string对应的key
也就是stringRef(如果是DOM节点就会对应DOM的实例,如果是子组件就对应组件的实例classComponent)
>但是如果是function Component呢,正常来说是会失败的,因为function Component是
>没有实例的,那怎么解决呢,后面的forward-ref(让我们在function Component使用ref也不会出错)
<p ref = "string"> asdf</p> 下一个大版本(React17)会废弃 ,ref会传入一个字符串,然后
//function 参数ele是节点对应的实例,DOM节点的实例,或者组件的实例
<p ref = {ele => (this.methodRef = ele) }></p>
//React提供给我们的一个API:首先在class Component中使用
this.objRef = React.createRef() 创建一个对象相当于//{current:null }
<p ref = {this.objRef}>asdf</p>
//然后把创建的对象(通过ref={}形式)传给某一个节点,就会把某个对象
的实例挂载到,current这个属性上面。
二、forwardRef
假设:当时纯函数组件的时候,没有实例对象,就不能使用获得对应的实例对象,follow me
import React, { Component } from 'react'
cosnt TargetComponent = (props,ref) => {
return <input type = "text" ref = {ref}/>
}
export default class Comp extends Component {
constructor() {
super();
this.ref = React.createRef();
//创建一个对象 { current : null }
}
componentDidMount() {
this.ref.current.value = "ref get input"
}
render() {
return <TargetComponent ref = {this.ref} />
}
}
那有同学就问:我自己定义的组件,我知道他是不是纯函数式组件,所以我会做一个判断用不用ref,
所以就不存在使用forwardRef来解决这个问题。
反驳:
1.如果我是一个组件的提供者,我开发了开源的组件,那我export之后,使用者不清楚这个是否是
纯函数组件(有没有实例)。
2.还有就是我们使用redux这种包,他会给我们提供一个方法connect,connect这个方法里面用到一个高阶
属性hoc(high order component),也就是通过调用connect传入我们自己定义的组件之后,返回的是包装
了这个组件的另外一个组件。如果我们直接传ref,这个ref对应的是被包装之后的组件,所以通过forward
实现了ref的传递(因为正常情况下我们是不能够通过下一层组件拿到ref这个属性的,因为他不属于props
里面)。
解决方案:
import React from 'react'
const TargetComponent = React.forwardRef((props,ref) => (
<input type = "text" ref = {ref} />
))
export default class Comp extends React.Component {
constructor(){
super();
this.ref = React.createRef();
}
componentDidMount() {
this.ref.current.value = "ref get input"
}
render() {
return <TargetComponent ref = {this.ref} />
//使用ref将节点或者组件实例传入this.ref这个对象{current:null}
}
}