react进阶-ref
2023-08-31 本文已影响0人
5cc9c8608284
ref
一.reference: 引用
场景:希望直接使用dom元素中的某个方法,或者希望直接使用自定义组件中的某个方法
- ref作用于内置的html组件,得到的将是真实的dom对象(内置的input,div等)
import React, { useRef,Component } from 'react'
export default class FocusMy extends Component {
handleClick=()=>{
this.refs.txt.focus()
}
render(){
return (
<div>
<input type="text" ref='txt' />
<button onClick={this.handleClick}>聚焦</button>
</div>
)
}
}
- ref作用于类组件,得到的将是类的实例
import React, { useRef,Component } from 'react'
class A extends Component{
method(){
console.log('调用了A组建的方法');
}
render(){
return <h1>组件A</h1>
}
}
export default class FocusMy extends Component {
handleClick=()=>{
// this.refs.txt.focus()
if(this.refs.refA){
this.refs.refA.method()//此处打印了 调用了A组建的方法
}
}
render(){
return (
<div>
<A ref='refA'></A>
<button onClick={this.handleClick}>聚焦</button>
</div>
)
}
}
- ref不能作用于函数组件
ref不再推荐使用字符串赋值,字符串赋值的方式将来可能会被移出
目前,ref推荐使用对象或者是函数
对象
通过 React.createRef 函数创建
import React, { Component } from 'react'
export default class Comp extends Component {
constructor(props){
super(props);
this.txt = React.createRef();
}
handleClick = () => {
this.txt.current.focus();
}
render() {
return (
<div>
<input ref={this.txt} type="text" />
<button onClick={this.handleClick}>聚焦</button>
</div>
)
}
}
函数
import React, { Component } from 'react'
export default class Comp extends Component {
state = {
show: true
}
handleClick = () => {
// this.txt.focus();
this.setState({
show: !this.state.show
});
}
componentDidMount() {
console.log("didMount", this.txt);
}
getRef = el => {
console.log("函数被调用了", el);
this.txt = el;
}
render() {
return (
<div>
{/* 写法一: */}
{
this.state.show && <input ref={this.getRef} type="text" />
}
<button onClick={this.handleClick}>显示/隐藏</button>
</div>
)
}
}
函数的调用时间:
- componentDidMount的时候会调用该函数
- 在componentDidMount事件中可以使用ref
- 如果ref的值发生了变动(旧的函数被新的函数替代),分别调用旧的函数以及新的函数,时间点出现在componentDidUpdate之前
- 旧的函数被调用时,传递null
- 新的函数被调用时,传递对象
- 如果ref所在的组件被卸载,会调用函数
谨慎使用ref
能够使用属性和状态进行控制,就不要使用ref。
- 调用真实的DOM对象中的方法
- 某个时候需要调用类组件的方法
二.ref转发
ref转发其实就是将父组件传过来的ref绑定到子组件内部的的某个元素或者组件身上,而不是绑定到子组件本身.
forwardRef方法:
- 参数,传递的是函数组件,不能是类组件,并且,函数组件需要有第二个参数来得到ref
- 返回值,返回一个新的组件
1.函数组件
import React, { Component } from 'react'
function A(props,ref){
return <>
<h1 ref={ref}>组件A</h1>
<span>{props.words}</span>
</>
}
const NewA=React.forwardRef(A)
export default class FocusMy extends Component {
refA=React.createRef();
componentDidMount(){
console.log(this.refA,'this.refA');
}
render() {
return (
<div>
<NewA words='abc' ref={this.refA} />
</div>
)
}
}
2.类组件
import React, { Component } from 'react'
class A extends Component{
render(){
return <>
<h1 ref={this.props.abc}>组件A</h1>
<span>{this.props.words}</span>
</>
}
}
const NewA=React.forwardRef((props,ref)=>{
return <A {...props} abc={ref}></A>
})
export default class FocusMy extends Component {
refA=React.createRef();
componentDidMount(){
console.log(this.refA,'this.refA');
}
render() {
return (
<div>
<NewA words='abc' ref={this.refA} />
</div>
)
}
}