内容简介:Refs 转发:将父组件创建的 ref 传递给子组件的某个dom元素(或组件)。让父组件可以直接操作该dom元素(或组件)一开始使用该技术的时候,分不清 传 自定义 ref prop 和 转发ref 有什么区别,本文稍微探讨下InputChild 为子组件,App 为父组件
前言
Refs 转发:将父组件创建的 ref 传递给子组件的某个dom元素(或组件)。让父组件可以直接操作该dom元素(或组件)
一开始使用该技术的时候,分不清 传 自定义 ref prop 和 转发ref 有什么区别,本文稍微探讨下
Demo: 父组件触发子组件的input元素获取焦点
InputChild 为子组件,App 为父组件
const InputChild = (props) => (
<input></input>
));
class App extends React.Component {
constructor() {
super()
this.icRef = React.createRef();
}
render () {
<InputChild ref={this.icRef}>Click me!</InputChild>;
}
}
按上面的操作,icRef 拿到的是 InputChild 组件,拿不到 InputChild 下的 input 元素。
比如想在父组件上让 InputChild 的 input 获取焦点,是不行的。
this.icRef.current.focus() //报错
InputChild 创建 ref 绑定 input
在 InputChild 上,利用 inputRef = React.createRef()
绑定 input,
然后父组件通过 ref.current.inputRef.current.focus()
获取焦点
class InputChild extends React.Component{
constructor(){
super()
this.inputRef = React.createRef()
}
render(){
return (
<input ref={this.inputRef}></input>
)
}
}
class App extends React.Component {
constructor() {
super()
this.icRef = React.createRef();
}
render () {
<InputChild ref={this.icRef}>Click me!</InputChild>;
}
}
this.ref.current.inputRef.current.focus() // input 获取焦点
Refs 转发
函数组件使用
const InputChild = React.forwardRef((props, ref) => (
<input ref={ref}>
</input>
));
class App extends React.Component {
constructor() {
super()
this.icRef = React.createRef();
}
handleClick = () => {
this.icRef.current.focus()
}
render () {
<>
<button onClick={this.handleClick}>Learn React</button>
<InputChild ref={this.icRef}>Click me!</InputChild>;
</>
}
}
点击 button 后,input 可以获取到焦点
Class 组件使用
function refProps(Component) {
return React.forwardRef((props, ref) => {
return <Component {...props} forwardedRef={ref} />;
});
}
@refProps
class InputChild extends React.Component{
render(){
const { forwardedRef } = this.props;
return (
<input ref={forwardedRef}></input>
)
}
}
效果同上,但是这里是 将 ref 绑定到新的prop上
尚未知道还有没有更好的做法
自定义 prop 属性
其实也可以直接定义一个 非ref 的prop,如下
class InputChild extends React.Component{
render(){
const { forwardedRef } = this.props;
return (
<input ref={forwardedRef}></input>
)
}
}
// 父组件使用
<InputChild forwardRef={this.ref} />
注意:函数式组件不能提供ref,否则对ref的访问将会失败,只能用 React.forwardRef()
传递 ref
效果是一样,但是对于上层使用者(不知道子组件代码的)来说, 第一想法是用 ref 绑定子组件而不是其他额外prop (forwardRef)
高阶组件上使用 refs 转发
需求:我们有一个 LogProps 高阶组件用于记录 props log,但是对 上层用户是不可见的
用户使用 <Child ref={this.ref}/>
。 ref 拿到的应该是 Child 而不是 高阶组件
错误使用
function logProps(WrappedComponent) {
class LogProps extends React.Component {
componentDidUpdate(prevProps) {
console.log('old props:', prevProps);
console.log('new props:', this.props);
}
render() {
return <WrappedComponent {...this.props} />;
}
}
return LogProps;
}
@logProps
class Child extends React.Component{
render(){
<div/>
}
}
<Child ref={this.ref}>Click me!</Child>;
this.ref
拿到的是 LogProps 组件,ref prop被消化,不会被传递到 Child
正确使用
function logProps(WrappedComponent) {
class LogProps extends React.Component {
componentDidUpdate(prevProps) {
console.log('old props:', prevProps);
console.log('new props:', this.props);
}
render() {
const {forwardedRef, ...rest} = this.props;
// Assign the custom prop "forwardedRef" as a ref
return <WrappedComponent ref={forwardedRef} {...rest} />;
}
}
return React.forwardRef((props, ref) => {
return <LogProps {...props} forwardedRef={ref} />;
});
}
@logProps
class Child extends React.Component{
render(){
<div/>
}
}
<Child ref={this.ref}>Click me!</Child>;
this.ref
拿到的是 Child 组件
Child 组件使用高阶组件,并且父组件的 ref 要绑定 Child下的 input元素
在以上的基础上,再转发一次
const InputChild = React.forwardRef((props, ref) => (
<input ref={ref}>
</input>
));
// 使用高阶组件对其进行封装
export default logProps(InputChild);
// 父组件中
<Child ref={this.ref}>Click me!</Child>;
父组件 this.ref.current.focus() 即可让 input 获取焦点
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
数据结构与算法分析
韦斯 / 机械工业 / 2007-1 / 55.00元
本书是国外数据结构与算法分析方面的标准教材,使用最卓越的Java编程语言作为实现工具讨论了数据结构(组织大量数据的方法)和算法分析(对算法运行时间的估计)。 随着计算机速度的不断增加和功能的日益强大,人们对有效编程和算法分析的要求也在增长。本书把算法分析与最有效率的Java程序的开发有机地结合起来,深入分析每种算法,内容全面、缜密严格,并细致讲解精心构造程序的方法。 第......一起来看看 《数据结构与算法分析》 这本书的介绍吧!