前言:
ref 在react中使用的频率还是挺高的,这里说说对于ref的理解。
1.定义
ref转发:是允许某些组件接受ref,并向下传递给子组件。
<B ref ={...} > <A /> </B>
这里面:理解有两层含义:1.B可以接受ref ; B 还能把ref 传递给子组件A。
1.1理解B 可以接受ref
定义子组件:子组件不需要任何的处理。
class ChildA extends PureComponent {
add =() => {
console.log('可以获取子组件的方法');
}
render() {
return (
<div> 我是一个子组件 </div>
)
}
};
定义父组件:
class Parent extends PureComponent {
childRef = createRef(); // 创建ref
handleClick =() => {
// 拿到子组件的实例,能够获取到子组件的数据和方法等。
console.log('拿到子组件的实例',this.childRef)
console.log('拿到子组件的实例',this.childRef.current.add())
}
render () {
return (
<div>
<button onClick={this.handleClick}>我是父组件的按钮</button>
{/* 接受ref */}
<ChildA ref={this.childRef} />
</div>
)
}
};
export default Parent;
1.2A能接受B的ref
新建一个子组件:
把父级传进来的ref传递给子组件的一个元素上,这样就可以操作对应元素的数据和方法。
const ChildB = React.forwardRef((props,ref) => {
// 子组件通过React.forwardRef 接收了一个ref
console.log('ref',ref)
return (
<input type="text" ref={ref} />
)
})
修改父级组件:
class Parent extends PureComponent {
childB = createRef();
handleClick =() => {
// 拿到子组件的实例,能够获取到子组件的数据和方法等。
console.log('拿到子组件的实例',this.childB.current.focus())
}
render () {
return (
<div>
<button onClick={this.handleClick}>我是父组件的按钮</button>
{/* 接受ref */}
<ChildB ref={this.childB} />
</div>
)
}
};export default Parent;
总结:1.ref是作为父子通信的另一种形式;2.父组件可以直接操作子组件(方法,数据,实例)。
2.函数式组件中使用ref
** 2.1父组件只要使用useRef().**
const ParentB:FC =() => {
const childCRef = useRef();
const handleClick =() => {
console.log('childCRef',childCRef)
};
return (
<div>
<button onClick={handleClick}>我是父组件的按钮</button>
<ChildC ref={childCRef} />
</div>
)
};
export default ParentB;
2.2 子组件暴露一些东西给父组件
1.函数式组件,必须通过 forwardRef 去传递
2.暴露给父级要通过useImperativeHandle
const ChildC =forwardRef( (props,ref) => {
useImperativeHandle(ref,() => ({
// 暴露给父组件的一些方法和数据
click:() => { },
value:'eq'
}));
return (
<div>
我是子组件
</div>
)
});
3.使用场景
使用场景:只要记住,父级想操作子组件的方法,获取子组件的实例信息,就可以用ref;但是ref实现细节暴露给父组件,不符合封装的隐蔽性,不可见行。