将子节点的ref暴露给父节点
16.3以上 Refs转发,将ref自动通过组件传递给子组件
1. 在父组件创建ref对象
2. 给子组件赋值ref
3. 通过React. forward向子组件转发ref属性
4. 父组件的ref对象指向子组件dom
5. ref参数只有在 React. forwardRef 组件内定义时可接受
const MyInput = React. forwardRef ( ( props, ref) => < input type = "text" placeholder= { props. placeholder} ref= { ref} / >
)
class App extends React . Component { constructor ( props) { super ( props) this . refInApp = React. createRef ( ) } componentDidMount ( ) { console . log ( '【APP】componentDidMount' , this . refInApp) } inputOperate = ( ) => { const oInput = this . refInApp. currentoInput. focus ( ) } render ( ) { return ( < > < MyInput ref= { this . refInApp} placeholder= "请输入" / > < button onClick= { this . inputOperate} > 聚焦< / button> < / > ) }
}
ReactDOM. render ( < App / > , document. getElementById ( 'app' )
)
在高阶组件中转发
匿名改具名
class MyInput extends React . Component { render ( ) { return ( < input type = "text" / > ) }
}
function InputHoc ( WrapperComponent) { class Input extends React . Component { render ( ) { const { forwardedRef, ... props } = this . propsreturn ( < WrapperComponent ref= { forwardedRef} { ... props} / > ) } } function forwardRef ( props, ref) { return < Input { ... props} forwardedRef= { ref} / > } forwardRef. displayName = 'Input-' + WrapperComponent. namereturn React. forwardRef ( forwardRef) }
const MyInputHoc = InputHoc ( MyInput)
class App extends React . Component { constructor ( props) { super ( props) this . refInApp = React. createRef ( ) } componentDidMount ( ) { console . log ( '【APP】componentDidMount' , this . refInApp) } inputOperate = ( ) => { const oInput = this . refInApp. currentoInput. focus ( ) } render ( ) { return ( < > { } < MyInputHoc ref= { this . refInApp} placeholder= "请输入" / > < button onClick= { this . inputOperate} > 聚焦< / button> < / > ) }
}
ReactDOM. render ( < App / > , document. getElementById ( 'app' )
)
16.2及以下 Refs转发
1. props传递
class MyInput extends React . Component { render ( ) { return ( < input type = "text" ref= { this . props. inputRef} placeholder= { this . props. placeholder} / > ) }
}
class App extends React . Component { constructor ( props) { super ( props) this . refInApp = React. createRef ( ) } componentDidMount ( ) { console . log ( '【APP】componentDidMount' , this . refInApp) } inputOperate = ( ) => { const oInput = this . refInApp. currentoInput. focus ( ) } render ( ) { return ( < > { } < MyInput inputRef= { this . refInApp} placeholder= "请输入" / > < button onClick= { this . inputOperate} > 聚焦< / button> < / > ) }
}
ReactDOM. render ( < App / > , document. getElementById ( 'app' )
)
2. 回调
class MyInput2 extends React . Component { constructor ( props) { super ( props) this . innerInput = null } setMyInput = ( el) => { console . log ( '回调的方式el' , el) this . innerInput = el; } inputOperate = ( ) => { this . innerInput. value = '' this . innerInput. focus ( ) } render ( ) { return ( < > < input type = "text" ref= { this . setMyInput} / > < button onClick= { this . inputOperate} > 聚焦 ( 回调方式) < / button> < / > ) }
}
3. 在父组件回调
class MyInput3 extends React . Component { render ( ) { return ( < input type = "text" ref= { this . props. inputRef} / > ) }
}
class App extends React . Component { componentDidMount ( ) { console . log ( '【APP】componentDidMount' , this . oInput) } inputOperate2 = ( ) => { this . oInput. focus ( ) } render ( ) { return ( < > < MyInput3 inputRef= { el => this . oInput = el} / > < button onClick= { this . inputOperate2} > 聚焦 ( 回调2 ,定义在父组件) < / button> < / > ) }
}
4. 字符串形式 已废弃
依赖组件实例下面的refs集合里的ref 需要React保持追踪当前正在渲染的组件(没有加载完成,this没法确定) 可能会比较慢 不能在render中工作 不能组合,只能有一个ref属性
class App extends React . Component { componentDidMount ( ) { console . log ( '【APP】componentDidMount字符串' , this . refs. inputRefText) } render ( ) { return ( < > < input type = "text" ref= "inputRefText" / > < / > ) }
}