组件分类
作为一个前端开发,我们可用的组件库相当丰富,有antd、mui、elementui等等,但是不是有了这些UI库后,我们在业务开发中就不用封装组件了,我把组件分为这么几类:
- Page组件,这种是页面级组件,一个页面就是一个组件,用于组织业务组件、通用组件和业务逻辑。
- 业务组件,这个级别的组件是包含了系统的特定业务逻辑且可复用的,比如我们系统中有一个流程图渲染组件,这就属于一个业务组件,业务组件中可以包含通用组件。
- 通用组件,这个是最细粒度级别的组件,比如一个按钮、标签、tabs等,在任何系统都会有这样的组件需求。
组件封装tip
这里介绍一些我在开发中的一些封装思路。
我们要封装组件要考虑两件事情。
- 复用级别。复用级别就是我上述所说的是属于哪种组件,业务组件和通用组件很好区分,包含了系统业务逻辑的就属于业务组件。
- 易用性,易用性涉及到props如何设计、文档是否完善、组件demo,如何让使用者使用简便,愿意去使用你封装的组件,这是一个很重要的指标。
下面我想主要围绕易用性讲一个例子,浏览器有一个API ResizeObserver,用于监听dom大小变化,我们在React使用通常是这样的
const ref = useRef();
const [sizeObj, setSizeObj] = useState({ width: 0, height: 0 });
useEffect(() => {
const resizeObserver = new ResizeObserver((entries) => {
const el = entries[0].target;
setSizeObj({
width: el.clientWidth,
height: el.clientHeight,
});
onResize(el, el.clientWidth, el.clientHeight);
});
resizeObserver.observe(ref.current);
return () => {
resizeObserver.disconnect();
};
}, []);
这段代码是固定范式,所以我们可以把它抽取成一个通用组件,在容器变化后把宽高状态向下传递渲染子组件,可以是这样的:
export default ({ className, style, onResize = () => {}, children }) => {
const ref = useRef();
const [sizeObj, setSizeObj] = useState({ width: 0, height: 0 });
useEffect(() => {
const resizeObserver = new ResizeObserver((entries) => {
const el = entries[0].target;
setSizeObj({
width: el.clientWidth,
height: el.clientHeight,
});
onResize(el, el.clientWidth, el.clientHeight);
});
resizeObserver.observe(ref.current);
return () => {
resizeObserver.disconnect();
};
}, []);
return (
<div ref={ref} style={style} className={className}>
{children(sizeObj)}
</div>
);
};
这个组件props很简单,className和style是为了控制容器的样式,onResize是宽高变化的回调,有时候外部需要这样的回调,children是要渲染的子组件,它是一个函数,通过把sizeObj传入来渲染。
这里的易用性体现在复用了代码,用户不用每次都写模版代码。
