09.ref的原理分析
在探究ref原理之前,我们先看看官方文档关于ref的说明:
- Refs provide a way to access DOM nodes or React elements created in the render method.
In the typical React dataflow, props are the only way that parent components interact with their children. To modify a child, you re-render it with new props. However, there are a few cases where you need to imperatively modify a child outside of the typical dataflow. The child to be modified could be an instance of a React component, or it could be a DOM element. For both of these cases, React provides an escape hatch.
- There are a few good use cases for refs : Managing focus, text selection, or media playback.Triggering imperative animations. Integrating with third-party DOM libraries.
- Don’t Overuse Refs
我们可以通过下面的代码来直观的感受下ref是什么: 我们在index.js中将代码做如下调整:
js
// index.js
// 注意这里用的是引入的官方原版源码,而不是我们编写的react源码
import React from 'react';
import ReactDOM from 'react-dom';
class MyClassComponent extends React.Component{
counter = 0
isBlue = false
constructor(props) {
super(props);
this.state = { count: '0' };
this.myRef = React.createRef();
}
updateShowText(newText){
this.setState({
count: newText
})
const element = this.myRef.current;
element.style.color = this.isBlue ? 'blue' : 'red'
this.isBlue = !this.isBlue
}
render(){
return <div className='test-class' ref={ this.myRef } style={
{
color: 'red',
cursor: 'pointer',
border: '1px solid gray',
borderRadius: '6px',
display: 'inline-block',
padding: '6px 12px'
}
} onClick={ () => this.updateShowText('' + ++this.counter) }>Simple React Counter: {this.state.count}</div>
}
}
ReactDOM.render(<MyClassComponent />, document.getElementById('root'))注意:在日常开发中,操作div元素的变化往往是通过数据来驱动的。但这里为了演示ref的能力,所以这里才用ref来改动样式。实际上,ref虽然很强大,但在日常开发中用的场景是有限的,正如官方文档说的:Managing focus, text selection, or media playback等特定场景下才利用ref的能力,如果滥用ref是与React世界中数据驱动视图的基本理念相违背的。
我们来根据这个ref的使用示范,来分析ref的实现原理,要让ref发挥作用有三个阶段:
- 初始化:
this.myRef = React.createRef();相当于 this.myRef = - 传递ref引用:
ref= { this.myRef },这里有个隐藏的动作,this.myRef.current = xxx dom - 取值:
const element = this.myRef.current;