开心兔 發表於 2020-4-12 10:37:00

React ref属性

<p><span style="font-size: 18px">简单来说,ref就是用来获取真实dom元素或者是组件实例的属性。</span></p>
<h1><span style="font-size: 18px">1. 创建和访问</span></h1>
<p><span style="font-size: 18px">ref 的值根据节点的类型而有所不同:</span></p>
<ul>
<li><span style="font-size: 18px">当&nbsp;<code class="gatsby-code-text">ref</code>&nbsp;属性用于 <span style="color: rgba(255, 0, 0, 1)">HTML 元素</span>时,构造函数中使用&nbsp;<code class="gatsby-code-text">React.createRef()</code>&nbsp;创建的&nbsp;<code class="gatsby-code-text">ref</code>&nbsp;接收底层 DOM 元素作为其&nbsp;<code class="gatsby-code-text">current</code>&nbsp;属性。</span></li>
<li><span style="font-size: 18px">当&nbsp;<code class="gatsby-code-text">ref</code>&nbsp;属性用于自定义 <span style="color: rgba(255, 0, 0, 1)">class 组件</span>时,<code class="gatsby-code-text">ref</code>&nbsp;对象接收组件的挂载实例作为其&nbsp;<code class="gatsby-code-text">current</code>&nbsp;属性。</span></li>
<li><span style="font-size: 18px">不能在函数组件上使用&nbsp;<code class="gatsby-code-text">ref</code>&nbsp;属性,因为他们没有实例。若是想用需要经过特殊处理</span></li>
</ul>
<h2><span style="font-size: 18px">1.1&nbsp;ref=字符串 (已经废弃)</span></h2>
<div class="cnblogs_code">
<pre><span style="font-size: 18px"><span style="color: rgba(0, 0, 0, 1)">class Cualculator extends React.Component {
add </span>=() =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    <span style="color: rgba(255, 0, 0, 1)">let num1 </span></span><span style="color: rgba(255, 0, 0, 1)">= parseInt(this.refs.num1.value)
    let num2 = parseInt(this</span><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(255, 0, 0, 1)">.refs.num2.value)</span>
    let result </span>= num1 +<span style="color: rgba(0, 0, 0, 1)">num2
    </span><span style="color: rgba(255, 0, 0, 1)">this.refs.result.value =</span><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(255, 0, 0, 1)"> result</span>
}
render() {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
      </span>&lt;div&gt;
      &lt;input <span style="color: rgba(255, 0, 0, 1)">ref="num1"</span> /&gt;+&lt;input <span style="color: rgba(255, 0, 0, 1)">ref="num2"</span>/&gt;&lt;button onClick={<span style="color: rgba(0, 0, 255, 1)">this</span>.add}&gt;=&lt;/button&gt;&lt;input <span style="color: rgba(255, 0, 0, 1)">ref="result"</span>/&gt;
      &lt;/div&gt;
<span style="color: rgba(0, 0, 0, 1)">    )
}
}</span></span></pre>
</div>
<div>
<div><span style="font-size: 18px">&nbsp;*&nbsp;num1:对应真实dom&nbsp;num1</span></div>
<div><span style="font-size: 18px">&nbsp;*&nbsp;num2:对应真实dom&nbsp;num2</span></div>
<h2><span style="font-size: 18px">1.2 ref=函数 (不推荐)</span></h2>
<div>
<div class="cnblogs_code">
<pre><span style="font-size: 18px"><span style="color: rgba(0, 0, 0, 1)">class Cualculator extends React.Component {
add </span>=() =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    <span style="color: rgba(255, 0, 0, 1)">let num1 </span></span><span style="color: rgba(255, 0, 0, 1)">= parseInt(this.num1.value)
    let num2 = parseInt(this</span><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(255, 0, 0, 1)">.num2.value)</span>
    let result </span>= num1 +<span style="color: rgba(0, 0, 0, 1)">num2
    </span><span style="color: rgba(255, 0, 0, 1)">this.result.value =</span><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(255, 0, 0, 1)"> result</span>
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">ref值是一个函数的时候,此函数会在虚拟dom转为真实dom插入也买你之后执行,参数就是真实dom</span>
<span style="color: rgba(0, 0, 0, 1)">render() {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
      </span>&lt;div&gt;
      &lt;input ref={<span style="color: rgba(255, 0, 0, 1)">instance</span> =&gt; <span style="color: rgba(0, 0, 255, 1)">this</span>.num1 = instance} /&gt;+&lt;input ref={<span style="color: rgba(255, 0, 0, 1)">instance</span> =&gt; this.num2 = instance}/&gt;&lt;button onClick={<span style="color: rgba(0, 0, 255, 1)">this</span>.add}&gt;=&lt;/button&gt;&lt;input ref={<span style="color: rgba(255, 0, 0, 1)">instance</span> =&gt; this.result = instance}/&gt;
      &lt;/div&gt;
<span style="color: rgba(0, 0, 0, 1)">    )
}
}</span></span></pre>
</div>
<h2><span style="font-size: 18px">1.3&nbsp;ref&nbsp;=&nbsp;React.createRef() (推荐使用)</span></h2>
<p><span style="font-size: 18px">通过React.createRef() 创建的ref属性有以下几个特点:</span></p>
<p><span style="font-size: 18px">当 ref 被传递给&nbsp;<code class="gatsby-code-text">render</code>&nbsp;中的元素时,对该节点的引用可以在 ref 的&nbsp;<span style="color: rgba(255, 0, 0, 1)"><code class="gatsby-code-text">current</code>&nbsp;</span>属性中被访问。</span></p>
<ul>
<li><span style="font-size: 18px">当&nbsp;<code class="gatsby-code-text">ref</code>&nbsp;属性用于&nbsp;<span style="color: rgba(255, 0, 0, 1)">HTML 元素</span>时,构造函数中使用&nbsp;<code class="gatsby-code-text">React.createRef()</code>&nbsp;创建的&nbsp;<code class="gatsby-code-text">ref</code>&nbsp;接收底层 DOM 元素作为其&nbsp;<code class="gatsby-code-text">current</code>&nbsp;属性。</span></li>
<li><span style="font-size: 18px">当&nbsp;<code class="gatsby-code-text">ref</code>&nbsp;属性用于自定义&nbsp;<span style="color: rgba(255, 0, 0, 1)">class 组件</span>时,<code class="gatsby-code-text">ref</code>&nbsp;对象接收组件的挂载实例作为其&nbsp;<code class="gatsby-code-text">current</code>&nbsp;属性。</span></li>
<li><span style="font-size: 18px">不能在<span style="color: rgba(255, 0, 0, 1)">函数组件</span>上使用&nbsp;<code class="gatsby-code-text">ref</code>&nbsp;属性,因为他们没有实例。若是想用需要经过特殊处理</span></li>
</ul>
<p><strong><span style="font-size: 18px">1.3.1 Html元素</span></strong></p>
</div>
<div>
<div class="cnblogs_code">
<pre><span style="font-size: 18px"><span style="color: rgba(0, 0, 0, 1)">class Cualculator extends React.Component {
constructor(){
    super()
    </span><span style="color: rgba(255, 0, 0, 1)">this.num1 = React.createRef()</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">{current:null} current在虚拟dom转为真实dom插入页面之后变成真实dom</span>
    <span style="color: rgba(255, 0, 0, 1)">this.num2 = React.createRef()</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">{current:null} current在虚拟dom转为真实dom插入页面之后变成真实dom</span>
    <span style="color: rgba(255, 0, 0, 1)">this.result = React.createRef()</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">{current:null} current在虚拟dom转为真实dom插入页面之后变成真实dom</span>
<span style="color: rgba(0, 0, 0, 1)">}
add </span>=() =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
    let num1 </span>= parseInt(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.<span style="color: rgba(255, 0, 0, 1)">num1.current</span>.value)
    let num2 </span>= parseInt(<span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.<span style="color: rgba(255, 0, 0, 1)">num2.current</span>.value)
    let result </span>= num1 +<span style="color: rgba(0, 0, 0, 1)">num2
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.<span style="color: rgba(255, 0, 0, 1)">result.current</span>.value =<span style="color: rgba(0, 0, 0, 1)"> result
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">ref值是一个函数的时候,此函数会在虚拟dom转为真实dom插入页面之后执行,参数就是真实dom</span>
<span style="color: rgba(0, 0, 0, 1)">render() {
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
      </span>&lt;div&gt;
      &lt;input ref={<span style="color: rgba(0, 0, 255, 1)">this</span>.num1} /&gt;+&lt;input ref={this.num2}/&gt;
      &lt;button onClick={<span style="color: rgba(0, 0, 255, 1)">this</span>.add}&gt;=&lt;/button&gt;
      &lt;input ref={<span style="color: rgba(0, 0, 255, 1)">this</span>.result}/&gt;
      &lt;/div&gt;
<span style="color: rgba(0, 0, 0, 1)">    )
}
}
ReactDOM.render(</span>&lt;Cualculator&gt;&lt;/Cualculator&gt;,document.getElementById('root'))</span></pre>
</div>
<p><span style="font-size: 18px">dom元素作为current属性的值</span></p>
<p><strong><span style="font-size: 18px">1.3.2 class组件</span></strong></p>
<div class="cnblogs_code">
<pre><span style="font-size: 18px"><span style="color: rgba(0, 0, 0, 1)">class UserName extends React.Component{
constructor(){
    super()
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.inputRef =<span style="color: rgba(0, 0, 0, 1)"> React.createRef()
}
render(){
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
      </span>&lt;input ref={<span style="color: rgba(0, 0, 255, 1)">this</span>.inputRef}&gt;&lt;/input&gt;
<span style="color: rgba(0, 0, 0, 1)">    )
}
}
class Form extends React.Component{
   constructor(){
   super()
   </span><span style="color: rgba(0, 0, 255, 1)">this</span>.username = <span style="color: rgba(255, 0, 0, 1)">React.createRef()</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">this.username 就是UserName组件的实例 this.username.current = new UserName()</span>
<span style="color: rgba(0, 0, 0, 1)">   }
   getFocus </span>= () =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
   </span><span style="color: rgba(0, 0, 255, 1)">this</span>.username.current.inputRef.current.focus() <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">this.username.current.inputRef.current 获取到组件对应的真实dom节点 就是 input框</span>
<span style="color: rgba(0, 0, 0, 1)">   }
render(){
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
      </span>&lt;form&gt;
      &lt;UserName <span style="color: rgba(255, 0, 0, 1)">ref={this.username}</span>/&gt;
      &lt;button type="button" onClick={<span style="color: rgba(0, 0, 255, 1)">this</span>.getFocus}&gt;让用户名获得焦点&lt;/button&gt;
      &lt;/form&gt;
<span style="color: rgba(0, 0, 0, 1)">    )
}
}</span></span></pre>
</div>
<p><span style="font-size: 18px">组件的实例等于current属性的值</span></p>
<p><strong><span style="font-size: 18px">1.3.3 函数组件</span></strong></p>
<div><span style="font-size: 18px">ref&nbsp;React.createRef()会获取到一个<span style="color: rgba(255, 0, 0, 1)">真实dom</span>或者是一个<span style="color: rgba(255, 0, 0, 1)">组件实例</span>对象&nbsp;但是函数组件没有实例,那怎么获取函数组件的ref属性,这个时候就需要特殊处理</span></div>
<div>
<div class="cnblogs_code">
<pre><span style="font-size: 18px"><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> UserName(props,ref) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> &lt;input <span style="color: rgba(255, 0, 0, 1)">ref={ref}</span>&gt;&lt;/input&gt;
<span style="color: rgba(0, 0, 0, 1)">}

const ForwordUsername </span>= <span style="color: rgba(255, 0, 0, 1)">React.forwardRef(UserName)</span>
<span style="color: rgba(0, 0, 0, 1)"> class Form extends React.Component{
   constructor(){
   super()
   </span><span style="color: rgba(0, 0, 255, 1)">this</span>.username = React.createRef() <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(255, 0, 0, 1)">this.username 就是ForwordUsername组件的实例 this.username.current = new ForwordUsername()</span>
<span style="color: rgba(0, 0, 0, 1)">   }
   getFocus </span>= () =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
   </span><span style="color: rgba(0, 0, 255, 1)">this</span>.username.current.focus() <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">this.username.current.inputRef.current 获取到组件对应的真实dom节点 就是 input框</span>
<span style="color: rgba(0, 0, 0, 1)">   }
render(){
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
      </span>&lt;form&gt;
      &lt;<span style="color: rgba(255, 0, 0, 1)">ForwordUsername</span> ref={<span style="color: rgba(255, 0, 0, 1)">this.username</span>}/&gt;
      &lt;button type="button" onClick={<span style="color: rgba(0, 0, 255, 1)">this</span>.getFocus}&gt;让用户名获得焦点&lt;/button&gt;
      &lt;/form&gt;
<span style="color: rgba(0, 0, 0, 1)">    )
}
}</span></span></pre>
</div>
<pre><span style="font-size: 18px">React.forwardRef会穿透UserName组件,获取到input的真实dom元素。<br></span></pre>
<h2><span style="font-size: 18px">1.4 React.forwardRef()的底层实现<br></span></h2>
<div class="cnblogs_code">
<pre><span style="font-size: 18px"><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> UserName(props,ref) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> &lt;input ref={ref}&gt;&lt;/input&gt;
<span style="color: rgba(0, 0, 0, 1)">}
</span>
<span style="color: rgba(255, 0, 0, 1)">function forwardRef (functionComponent) {
return class extends React.Component {
    render() {
      return functionComponent(this.props,this</span><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(255, 0, 0, 1)">.props.ref2)
    }
}
}</span>
const ForwordUsername </span>= forwardRef(UserName) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">React.forwardRef返回一个类组件,将这个类组件传给</span>
<span style="color: rgba(0, 0, 0, 1)"> class Form extends React.Component{
   constructor(){
   super()
   </span><span style="color: rgba(0, 0, 255, 1)">this</span>.username = React.createRef() <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">this.username 就是UserName组件的实例 this.username.current = new UserName()</span>
<span style="color: rgba(0, 0, 0, 1)">   }
   getFocus </span>= () =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
   </span><span style="color: rgba(0, 0, 255, 1)">this</span>.username.current.focus() <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">this.username.current.inputRef.current 获取到组件对应的真实dom节点 就是 input框</span>
<span style="color: rgba(0, 0, 0, 1)">   }
render(){
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
      </span>&lt;form&gt;
      &lt;ForwordUsername <span style="color: rgba(255, 0, 0, 1)">ref2</span>={<span style="color: rgba(0, 0, 255, 1)">this</span>.username}/&gt;
      &lt;button type="button" onClick={<span style="color: rgba(0, 0, 255, 1)">this</span>.getFocus}&gt;让用户名获得焦点&lt;/button&gt;
      &lt;/form&gt;
<span style="color: rgba(0, 0, 0, 1)">    )
}
}</span></span></pre>
</div>
<p><span style="font-size: 18px">它是将函数组件转换成了类组件,当然也可以直接返回一个转化之后的函数组件</span></p>
<div class="cnblogs_code">
<pre><span style="font-size: 18px"><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> UserName(<span style="color: rgba(255, 0, 0, 1)">props</span>) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> &lt;input ref={props.<span style="color: rgba(255, 0, 0, 1)">ref2</span>}&gt;&lt;/input&gt;
<span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">函数组件没有this,可以通过</span>
<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> forwardRef (functionComponent) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(255, 0, 0, 1)">props =&gt;</span><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(255, 0, 0, 1)"> functionComponent(props,props.ref2)</span>
}
const ForwordUsername </span>= forwardRef(UserName) <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">React.forwardRef返回一个类组件,将这个类组件传给</span>
<span style="color: rgba(0, 0, 0, 1)"> class Form extends React.Component{
   constructor(){
   super()
   </span><span style="color: rgba(0, 0, 255, 1)">this</span>.username = React.createRef() <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">this.username 就是UserName组件的实例 this.username.current = new UserName()</span>
<span style="color: rgba(0, 0, 0, 1)">   }
   getFocus </span>= () =&gt;<span style="color: rgba(0, 0, 0, 1)"> {
   </span><span style="color: rgba(0, 0, 255, 1)">this</span>.username.current.focus() <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">this.username.current.inputRef.current 获取到组件对应的真实dom节点 就是 input框</span>
<span style="color: rgba(0, 0, 0, 1)">   }
render(){
    </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> (
      </span>&lt;form&gt;
      &lt;ForwordUsername <span style="color: rgba(255, 0, 0, 1)">ref2</span>={<span style="color: rgba(0, 0, 255, 1)">this</span>.username}/&gt;
      &lt;button type="button" onClick={<span style="color: rgba(0, 0, 255, 1)">this</span>.getFocus}&gt;让用户名获得焦点&lt;/button&gt;
      &lt;/form&gt;
<span style="color: rgba(0, 0, 0, 1)">    )
}
}
ReactDOM.render(</span>&lt;Form&gt;&lt;/Form&gt;,document.getElementById('root'))</span></pre>
</div>
<h2><span style="font-family: &quot;PingFang SC&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif; font-size: 18px">1.5 Refs 使用场景</span></h2>
<ul>
<li><span style="font-size: 18px">处理焦点、文本选择或者媒体的控制</span></li>
<li><span style="font-size: 18px">触发必要的动画</span></li>
<li><span style="font-size: 18px">集成第三方 DOM 库</span></li>
</ul>
<pre><span style="font-size: 18px">补充:<br></span></pre>
<p><span style="font-size: 18px">函数组件执行完毕之后就被释放了,但是会返回一个react元素,这个元素会一直存在,最后会被渲染成真实dom</span></p>
<p>&nbsp;</p>
<pre><span style="font-size: 18px">&nbsp;</span></pre>
</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
</div>

</div>
<div id="MySignature" role="contentinfo">
    不积跬步无以至千里<br><br>
来源:https://www.cnblogs.com/lyt0207/p/12684036.html
頁: [1]
查看完整版本: React ref属性