您好,如果喜欢我的文章,可以关注我的公众号「量子前端」,将不定期关注推送前端好文~
头像组件文档如下:
所提供的的API能力如下:
封装思路主要由Avatar和AvatarGroup两个组件完成,用户可以单Avatar来使用,当头像比较多可以采用AvatarGroup进行控制,因此还是由Group创建Context上下文,来对Avatar进行整体控制。
源码如下: Avatar.tsx:
import React, { FC, useContext, useEffect, memo, useMemo, useRef } from 'react';
import { ctx } from './group';
import { avatarProps, avatarStyles } from './interface';
import './styles/avatar.module.less';
const Avatar: FC<avatarProps> = (props) => {
const {
children,
style = {},
size = 40,
shape,
autoFixFontSize = true,
triggerType = 'button',
triggerIcon,
triggerClick,
} = props;
const groupProps = useContext(ctx);
const textRef = useRef(null);
useEffect(() => {
autoFixFontSizeHandler();
}, []);
const autoFixFontSizeHandler = () => {
if (autoFixFontSize) {
//如果用户配置了文本自适应
if (textRef.current) {
const textDomWidth = (textRef.current as HTMLElement).clientWidth;
const avatarSize = groupProps.size || size || 40;
if (textDomWidth - avatarSize > 0) {
//文本不够,需要自适应
(textRef.current as HTMLElement).style.transform = `scale(${
1 - (textDomWidth - avatarSize + 5) / 100
})`;
console.log(textDomWidth, avatarSize);
}
}
}
};
const formatStyle = useMemo(() => {
//整合所有头像传参样式
const returnStyle: avatarStyles = { ...groupProps.groupStyle, ...style };
if (Object.keys(groupProps).length > 0) {
//头像组
if (groupProps.size) {
returnStyle.width = `${groupProps.size}px`;
returnStyle.height = `${groupProps.size}px`;
returnStyle.fontSize = `${groupProps.size / 3}px`;
}
} else {
//单头像
if (size) {
returnStyle.width = `${size}px`;
returnStyle.height = `${size}px`;
returnStyle.fontSize = `${size / 3}px`;
}
}
if (shape && shape === 'square') {
returnStyle.borderRadius = '5px';
}
return returnStyle;
}, [style, shape, size, groupProps]);
const buttonDialogTransform = useMemo(() => {
return shape == 'square' ? { right: '-2px', bottom: '-2px' } : { right: '2px', bottom: '-2px' };
}, [triggerType]);
const handleClick = () => {
triggerClick && triggerClick();
};
return (
<div className="avatar" style={formatStyle}>
{children && (children as any).type === 'img' ? (
children
) : (
<div ref={textRef} className="text-ref">
{children}
</div>
)}
{
//按钮式dialog
triggerType === 'button' && triggerIcon && (
<div className="button-dialog" style={buttonDialogTransform} onClick={handleClick}>
{triggerIcon}
</div>
)
}
{
//内嵌式dialog
triggerType === 'mask' && triggerIcon && (
<div className="dialog">
<div className="icon" onClick={handleClick}>
{triggerIcon}
</div>
</div>
)
}
</div>
);
};
export default memo(Avatar);
AvatarGroup.tsx:
import React, { createContext, FC, memo } from 'react';
import { groupProps } from './interface';
import './styles/group.module.less';
export const ctx = createContext<any>({} as any); //顶层通信装置
const AvatarGroup: FC<groupProps> = (props) => {
const { children, size, groupStyle = {} } = props;
const groupProps = props;
return (
<ctx.Provider value={groupProps}>
<div className="avatar-group">{children}</div>
</ctx.Provider>
);
};
export default memo(AvatarGroup);
组件库目前也是完成了一部分了,也慢慢开始成型了,上文加入了组件埋点+后端管理信息,最后留一下组件库的信息:
- Concis组件库线上链接:react-view-ui.com:92
- github:github.com/fengxinhhh/…
- npm:www.npmjs.com/package/con…
开源不易,欢迎学习和体验,喜欢请多多支持,有问题请留言。