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">当 <code class="gatsby-code-text">ref</code> 属性用于 <span style="color: rgba(255, 0, 0, 1)">HTML 元素</span>时,构造函数中使用 <code class="gatsby-code-text">React.createRef()</code> 创建的 <code class="gatsby-code-text">ref</code> 接收底层 DOM 元素作为其 <code class="gatsby-code-text">current</code> 属性。</span></li>
<li><span style="font-size: 18px">当 <code class="gatsby-code-text">ref</code> 属性用于自定义 <span style="color: rgba(255, 0, 0, 1)">class 组件</span>时,<code class="gatsby-code-text">ref</code> 对象接收组件的挂载实例作为其 <code class="gatsby-code-text">current</code> 属性。</span></li>
<li><span style="font-size: 18px">不能在函数组件上使用 <code class="gatsby-code-text">ref</code> 属性,因为他们没有实例。若是想用需要经过特殊处理</span></li>
</ul>
<h2><span style="font-size: 18px">1.1 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>=() =><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><div>
<input <span style="color: rgba(255, 0, 0, 1)">ref="num1"</span> />+<input <span style="color: rgba(255, 0, 0, 1)">ref="num2"</span>/><button onClick={<span style="color: rgba(0, 0, 255, 1)">this</span>.add}>=</button><input <span style="color: rgba(255, 0, 0, 1)">ref="result"</span>/>
</div>
<span style="color: rgba(0, 0, 0, 1)"> )
}
}</span></span></pre>
</div>
<div>
<div><span style="font-size: 18px"> * num1:对应真实dom num1</span></div>
<div><span style="font-size: 18px"> * num2:对应真实dom 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>=() =><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><div>
<input ref={<span style="color: rgba(255, 0, 0, 1)">instance</span> => <span style="color: rgba(0, 0, 255, 1)">this</span>.num1 = instance} />+<input ref={<span style="color: rgba(255, 0, 0, 1)">instance</span> => this.num2 = instance}/><button onClick={<span style="color: rgba(0, 0, 255, 1)">this</span>.add}>=</button><input ref={<span style="color: rgba(255, 0, 0, 1)">instance</span> => this.result = instance}/>
</div>
<span style="color: rgba(0, 0, 0, 1)"> )
}
}</span></span></pre>
</div>
<h2><span style="font-size: 18px">1.3 ref = React.createRef() (推荐使用)</span></h2>
<p><span style="font-size: 18px">通过React.createRef() 创建的ref属性有以下几个特点:</span></p>
<p><span style="font-size: 18px">当 ref 被传递给 <code class="gatsby-code-text">render</code> 中的元素时,对该节点的引用可以在 ref 的 <span style="color: rgba(255, 0, 0, 1)"><code class="gatsby-code-text">current</code> </span>属性中被访问。</span></p>
<ul>
<li><span style="font-size: 18px">当 <code class="gatsby-code-text">ref</code> 属性用于 <span style="color: rgba(255, 0, 0, 1)">HTML 元素</span>时,构造函数中使用 <code class="gatsby-code-text">React.createRef()</code> 创建的 <code class="gatsby-code-text">ref</code> 接收底层 DOM 元素作为其 <code class="gatsby-code-text">current</code> 属性。</span></li>
<li><span style="font-size: 18px">当 <code class="gatsby-code-text">ref</code> 属性用于自定义 <span style="color: rgba(255, 0, 0, 1)">class 组件</span>时,<code class="gatsby-code-text">ref</code> 对象接收组件的挂载实例作为其 <code class="gatsby-code-text">current</code> 属性。</span></li>
<li><span style="font-size: 18px">不能在<span style="color: rgba(255, 0, 0, 1)">函数组件</span>上使用 <code class="gatsby-code-text">ref</code> 属性,因为他们没有实例。若是想用需要经过特殊处理</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>=() =><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><div>
<input ref={<span style="color: rgba(0, 0, 255, 1)">this</span>.num1} />+<input ref={this.num2}/>
<button onClick={<span style="color: rgba(0, 0, 255, 1)">this</span>.add}>=</button>
<input ref={<span style="color: rgba(0, 0, 255, 1)">this</span>.result}/>
</div>
<span style="color: rgba(0, 0, 0, 1)"> )
}
}
ReactDOM.render(</span><Cualculator></Cualculator>,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><input ref={<span style="color: rgba(0, 0, 255, 1)">this</span>.inputRef}></input>
<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>= () =><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><form>
<UserName <span style="color: rgba(255, 0, 0, 1)">ref={this.username}</span>/>
<button type="button" onClick={<span style="color: rgba(0, 0, 255, 1)">this</span>.getFocus}>让用户名获得焦点</button>
</form>
<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 React.createRef()会获取到一个<span style="color: rgba(255, 0, 0, 1)">真实dom</span>或者是一个<span style="color: rgba(255, 0, 0, 1)">组件实例</span>对象 但是函数组件没有实例,那怎么获取函数组件的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> <input <span style="color: rgba(255, 0, 0, 1)">ref={ref}</span>></input>
<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>= () =><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><form>
<<span style="color: rgba(255, 0, 0, 1)">ForwordUsername</span> ref={<span style="color: rgba(255, 0, 0, 1)">this.username</span>}/>
<button type="button" onClick={<span style="color: rgba(0, 0, 255, 1)">this</span>.getFocus}>让用户名获得焦点</button>
</form>
<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> <input ref={ref}></input>
<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>= () =><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><form>
<ForwordUsername <span style="color: rgba(255, 0, 0, 1)">ref2</span>={<span style="color: rgba(0, 0, 255, 1)">this</span>.username}/>
<button type="button" onClick={<span style="color: rgba(0, 0, 255, 1)">this</span>.getFocus}>让用户名获得焦点</button>
</form>
<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> <input ref={props.<span style="color: rgba(255, 0, 0, 1)">ref2</span>}></input>
<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 =></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>= () =><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><form>
<ForwordUsername <span style="color: rgba(255, 0, 0, 1)">ref2</span>={<span style="color: rgba(0, 0, 255, 1)">this</span>.username}/>
<button type="button" onClick={<span style="color: rgba(0, 0, 255, 1)">this</span>.getFocus}>让用户名获得焦点</button>
</form>
<span style="color: rgba(0, 0, 0, 1)"> )
}
}
ReactDOM.render(</span><Form></Form>,document.getElementById('root'))</span></pre>
</div>
<h2><span style="font-family: "PingFang SC", "Helvetica Neue", 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> </p>
<pre><span style="font-size: 18px"> </span></pre>
</div>
<p> </p>
<p> </p>
</div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
</div>
</div>
<div id="MySignature" role="contentinfo">
不积跬步无以至千里<br><br>
来源:https://www.cnblogs.com/lyt0207/p/12684036.html
頁:
[1]