一、项目背景
本项目使用 umi + react + antd 搭建,react 内部使用函数组件书写。
二、需要解决的问题及解决方案
- 父组件调用子组件内的方法:父组件若想调用子组件内的方法需使用 ref,但父组件是函数组件,因此不能使用 CreateRef 方法创建 ref,需要使用 Hooks 中的 useRef 方法创建 ref。代码如下:
// 父组件代码
import { useRef } from "react";
import SonComponent from "./SonComponent";
export default function ParentComponent () {
const showRef = useRef;
const handleClick = () => {
// 先判断 showRef.current 是否存在,如果不判断直接调用子组件方法会报错
if (showRef.current) {
// 调用子组件方法,showPanel 为子组件内方法
showRef.current.showPanel();
};
};
return (
<div>
<button onClick={ handleClick }>点击调用子组件方法</button>
<SonComponent ref={showRef} />
</div>
)
};
子组件为函数组件,将子组件内的方法暴露出来需要调用 forwardRef 方法和 useImperativeHandle 方法。代码如下:
// 子组件代码
import { forwardRef, useImperativeHandle } from "react";
function SonComponent (props, ref) {
const {} = props;
const showPanel = () => {
console.log('子组件方法')
};
useImperativeHandle(ref, () => ({
showPanel,
}));
return (
<div>
// 子组件内容
</div>
);
};
export default forwardRef(SonComponent);
但如果子组件内已经调用了 connect 方法,此时 connect 如果包裹 forwardRef 的话,那么子组件中的方法无法暴露到父组件,会导致父组件无法调用子组件中的方法,应让 forwardRef 方法包裹 connect 方法。代码如下:
// 父组件代码不变
// 子组件代码
import { useEffect, useState, forwardRef, useImperativeHandle } from "react";
import { connect } from "dva";
let SonComponent = (props: any) => {
const { refInstance } = props;
const showPanel = () => {
console.log('子组件方法')
};
useImperativeHandle(refInstance, () => ({
showPanel,
}));
return (
<div>
// 子组件内容
</div>
);
};
const mapStateToProps = (state: any) => ({});
SonComponent = connect(mapStateToProps)(SonComponent);
// 此处使用 refInstance 替代 ref 避免与 ref 重名(百度的,我不懂为啥,没做尝试)
export default forwardRef((props, ref) => (
<SonComponent {...props} refInstance={ref} />
));
- 滚动条样式修改:客户要求无论多少条列表内容全部显示,但又不能有滚动条,我不知道怎么在滚动条去掉的同时保留滚动条的功能,于是我选择把滚动条变窄。代码如下:
// css 文件
.showList {
min-height: 50px;
max-height: 350px;
overflow-y: scroll;
}
.showList::-webkit-scrollbar {
width: 5px;
}