持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第30天,点击查看活动详情
React 中有两个创建 ref 的方法,createRef() 和 useRef()。使用 ref,只需要将创建的 ref 赋到 DOM 和类组件的 ref 属性上即可。当组件挂载之后,ref 的 current 属性访问的就是对该节点的引用,DOM 元素时就是该元素,类组件时就是该组件的实例。
createRef
this.inputRef = createRef()
<input ref={this.inputRef}>
由于ref 的 current 属性访问的就是对该节点的引用,DOM 元素时就是该元素 ,所以打印this.inputRef.current可以得到input这个真实dom。
ref也可以用在父子组件中用来传值:
子组件为Child组件
父组件app中引用:
this.ChildRef = createRef()
< Child ref={this.ChildRef}/>
通过在app中就可以使用this.ChildRef.current打印出Child这个子组件了,如果Child中有value/state这些可以一并打印出来
useRef--针对函数组件的基础使用
原生dom,非受控
function App(){
const [value,setValue] = useState("zhangsan")
const inputRef = useRef() //{current=null}
const handleSubmit = ()=>{
//获取input数据
const name = inputRef.current.value
console.log(name)
//可以打印到zhangsan
setValue(name)
}
return(
<div>
<input type="text" ref={this.inputRef} value={value}/>
<button onClick={ handleSubmit } >提交</button>
</div>
)
}
对比:受控方式
<input type="text" ref={this.inputRef} value={value} onChange=(e)=>{setValue(e.target.value)}/>
未解决问题
捕获值问题:
场景,在输入框中输入信息后,点击提交,然后立即在5s内在输入,观察打印的是第一次输入的值还是连带着最后一次输入的值。
先定义好input中的value数据
const [value,setValue] = useState('')
然后来显示value
<input type="text" value={value} />
在input上放onChange点击事件,实时获取到输入的数据
handleChange=(e)=>{
setValue(e.target.value)
}
现在可以实时同步value数据了,那点击按钮将在5s之后弹出我输入的数据
const handleSubmit = () =>{
setTimeout(()=>{
alert(value) //弹出value
},5000)
}
输入aaa,点击按钮在5s之后弹窗,在此之际未到5s之后再次输入sss。请问是输出aaa还是aaasss呢?
//源代码
function App1(){
const [value,setValue] = useState('')
const handleChange=(e)=>{
setValue(e.target.value)
}
const handleClick=()=>{
setTimeout(() => {
alert(value)
}, 5000);
}
return(
<div>
<input type="text" value={value} onChange={handleChange} />
<button onClick={handleClick}>按钮</button>
</div>
)
}
结果打印aaa
原因是,在函数组件中使用useState时,创建的变量是类似存在于闭包机制,打印的并不是实时同步的value,变量的地址是前后不一致的,所以打印的是之前输入的数据。
那接下来要做的就是解决闭包机制,让input这个真实dom中的value等于实时输入的value
用到useRef啦!
在input组件中使用ref来获取真实dom
const lastValue = useRef()
return(
<input type="text" ref={lastValue} />
)
这样就可以获取lastValue.current值为input真实dom了。
下面就要将真实dom上的value弹窗出来。
setTimeout(()=>{
const value = lastValue.current.value
alert(value)
},5000)
会打印出来的,我确信。
//源代码
function App(){
const lastValue = useRef()
const handleClick=()=>{
setTimeout(() => {
const value = lastValue.current.value
alert(value)
}, 5000);
}
return(
<div>
<input type="text" ref={lastValue} />
<button onClick={handleClick}>按钮</button>
</div>
)
}
直接打印真实dom上的value就好啦,无需通过useState存放value值再打印。
说了这么多函数组件,那来看看类组件中是什么样呢?
类组件
同样是输入框和按钮
<input type="text" value={value} onChange={handleChange} />
<button onClick={handleSubmit}>按钮</button>
设置createRef()
const lastValue = createRef()
将lastValue中的current对象设置为输入的数据,然后打印lastValue中的current
const handleChange = (e) =>{
setValue(e.target.value)
lastValue.current = e.target.value
}
const handleSubmit = ()=>{
setTimeout(()=>{
alert(lastValue.current)
},5000)
}
return(
<input type="text" value={value} onChange={handleChange} />
<button onClick={handleSubmit}>按钮</button>
)
直接运行查看结果
类组件中不存在闭包机制的问题,可以直接打印出在5s中输入的内容。