将子节点的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.current
oInput.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.props
return (
<WrapperComponent ref={forwardedRef} {...props} />
)
}
}
function forwardRef(props, ref) {
return <Input {...props} forwardedRef={ref} />
}
forwardRef.displayName = 'Input-' + WrapperComponent.name
return 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.current
oInput.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.current
oInput.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" />
</>
)
}
}
