我們知道在react中,常用props實現子組件數據到父組件的傳遞,但是父組件調用子組件的功能卻不常用。文檔上說ref其實不是最佳的選擇,但是想著偷懶不學redux,在網上找了很多教程,要不就是hook的講的太少,要不就是父子組件傻傻分不清,於是只好再啃了一下文檔,就學了一下其它hook的api。 ...
我們知道在react中,常用props實現子組件數據到父組件的傳遞,但是父組件調用子組件的功能卻不常用。文檔上說ref其實不是最佳的選擇,但是想著偷懶不學redux,在網上找了很多教程,要不就是hook的講的太少,要不就是父子組件傻傻分不清,於是只好再啃了一下文檔,就學了一下其它hook的api。
在這裡我們需要用到useImperativeHandle
這個api,其函數形式為
useImperativeHandle(ref, createHandle, [deps])
其實這個api也是ref的一種形式,但是相當於做了一定的優化,可以選擇讓子組件只暴露一定的api給父組件,根據在文檔和其他博客上給出的方法,一共有兩大步驟:
- 將ref傳遞到子組件中
- 需要使用forwardRef對子組件進行包裝
子組件MyWorldMap
const mapRef = useRef(null);
useImperativeHandle(ref, () => {
return {
//clickSwitch是子組件暴露的函數
clickSwitch() {
if(type == 1){
initChinaMap();
setType(2);
}else{
initWordMap();
setType(1);
}
}
}
})
//你的return內容,註意ref
return(
<React.Fragment>
<div id={"myWorldMap"} style={{ width: "800px", height: "400px" }} ref={mapRef}></div>
</React.Fragment>
)
}
//最後要配合forwardRef
MyWorldMap = forwardRef(MyWorldMap);
export default MyWorldMap;
註:ref是子組件聲明的時候傳進來的,也就是
function MyWorldMap (props,ref){
//..你的代碼
}
//export...
其實官方文檔給出來的例子是:
function FancyInput(props, ref) {
const inputRef = useRef();
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
}
}));
return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);
兩種方法都是可以的
父組件MyTrip
const myWordMapRef = useRef();
return(
//省略一些代碼,註意ref
<MyWorldMap proData = { myMapData} handleMapClick = {handleMapClick.bind(this)} ref={myWordMapRef}>
</MyWorldMap>
<div className={styles["mapButton-wrap"]}>
<ButtonGroup>
<Button onClick={() => myWordMapRef.current.clickSwitch()}>Switch</Button>
<Button onClick={()=>clickAll() }>All</Button>
</ButtonGroup>
</div>
)
現在你就可以在父組件裡面通過myWordMapRef.current.clickSwitch()
調用函數了