持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第31天,点击查看活动详情
接上篇,如果在父子组件之间传递ref转发,一般是在父组件中定义好,再传递给子组件使用。
如下:
App父组件
const lastValue = useRef()
------------------------------
<Child inputRef={inputRef}/>
然后在子组件中通过传统的props接收inputRef
function Child(props){
const {inputRef} = props
return(
<input type="text" ref={inputRef} />
)
}
现使用新方式-------ref转发
在react中有一个forwardRef方式可以用来专门转发ref,使用方式如下:
同样在app组件中定义好useRef,
const inputRef = useRef()//current:null
不同点:直接转发ref至子组件
要转发给哪个子组件,就包裹住谁
const ForwardChild = forwardRef(Child)
使用完转发方法,就可以在父组件中通过ref转发inputRef了
<ForwardChild ref={inputRef}/>
原本是:记住差别哦
<Child inputRef={inputRef}/>
接下来就可以跑去子组件中接收并使用ref啦
function Child(props,ref){
console.log(props,"props");
console.log(ref,"ref");
return(
<input type="text" ref={ref}/>
)
}
此时打印props属性,它里面为空,因为通过forward方式就不会涉及到props传递了。
那打印第二个参数ref,可以观察到里面有current有inputRef了。
直接就可以在ref处引用父组件传来的“ref”咯
场景升级,当点击按钮时,进行获取焦点的操作:
<ForwardChild ref={inputRef}/>
<button onClick={focus}>按钮</button>
定义方法:
const focus=()=>{
inputRef.current.focus()
}
点击就可以调用真实dom上的方法focus了。
那也可以点击按钮删除该真实dom
inputRef.current.parentNode.removeChild(inputRef.current)
这样很危险啊,如果随便定义方法都可以使用的话那岂不是赤裸裸了嘛。
于是引入新钩子函数useImperativeHandle转发权限
在转发权限中设置对象,內部可以有很多可以被允许的方法,只有在这里暴露的权限才能被使用,如果没有被定义过却仍然使用的话,那结果就是失败并报错。
步骤,来到子组件中,浅试一下,暴露两个方法吧
const inputRef = useRef()
const childHandle =()=>{
console.log("child inner other function");
}
useImperativeHandle(ref,()=>{
return{
focus:()=>{
inputRef.current.focus()
},
childHandle:()=>{
childHandle
}
}
})
return(
<input type="text" ref={inputRef}/>
)
于是,就可以来到父组件中使用这两个被暴露的方法了
const focus=()=>{
inputRef.current.focus()
}
此时如果再删除节点的话就会报错了。所以暴露权限成功。