Concis组件库封装——Popover气泡卡片

简介: Concis组件库封装——Popover气泡卡片组件记录

您好,如果喜欢我的文章,可以关注我的公众号「量子前端」,将不定期关注推送前端好文~

气泡卡片...顾名思义,移动到或点击某块区域,出现一个气泡卡片dialog,组件库文档如下:

在这里插入图片描述
在这里插入图片描述
主要支持的有移动或点击触发,以及不同方向的气泡卡片,并提供了气泡卡片宽度,内容为调用端的DOM,样式也在调用端所控制。
API能力如下:
在这里插入图片描述
源码如下:

import React, {
   
   
  FC,
  memo,
  ReactNode,
  useState,
  useEffect,
  useMemo,
  useRef,
} from 'react';
import lodash from 'loadsh';
import './index.module.less';

interface popoverProps {
   
   
  children?: ReactNode;
  /**
   * @description 触发形式 hover/click
   * @default hover
   */
  type?: string;
  /**
   * @description 对齐方式 left/right/top/bottom
   * @default bottom
   */
  align?: string;
  /**
   * @description 卡片内容
   * @default <></>
   */
  content: ReactNode;
  /**
   * @description 卡片宽度
   * @default 200px
   */
  dialogWidth?: number;
  /**
   * @description 提供给调用层的卡片显示隐藏状态
   * @default false
   */
  propsVisiable?: boolean;
  /**
   * @description 卡片显示隐藏回调
   */
  onVisableChange?: Function;
}
type alignStyle = {
   
   
  left?: string;
  right?: string;
  top?: string;
  bottom?: string;
};
const Popover: FC<popoverProps> = (props) => {
   
   
  const {
   
   
    children,
    type = 'hover',
    align = 'bottom',
    content,
    dialogWidth = 200,
    propsVisiable,
    onVisableChange,
  } = props;

  const showBtnRef = useRef();
  const [showDialog, setShowDialog] = useState<boolean>(propsVisiable || false); //是否显示
  const [showBtnSize, setShowBtnSize] = useState({
   
   
    width: '',
    height: '',
  });

  useEffect(() => {
   
   
    setShowBtnSize({
   
   
      width: (showBtnRef.current as any).offsetWidth,
      height: (showBtnRef.current as any).offsetHeight,
    });
    if (type == 'click') {
   
   
      window.addEventListener('click', () => {
   
   
        setShowDialog(false);
        if (propsVisiable) {
   
   
          setShowDialog(false);
        }
      });
    }
  }, []);

  useEffect(() => {
   
   
    if (propsVisiable != undefined) {
   
   
      console.log('执行');
      setShowDialog(propsVisiable as boolean);
    }
  }, [propsVisiable]);
  const clickToggleDialog = (e: any) => {
   
   
    //点击打开dialog
    e.stopPropagation();
    if (type == 'click') {
   
   
      setShowDialog(!showDialog);
      onVisableChange && onVisableChange(!showDialog);
    }
  };
  const hoverOpenDialog = lodash.debounce(() => {
   
   
    //移入打开dialog
    if (type == 'hover' && showDialog == false) {
   
   
      setShowDialog(true);

      onVisableChange && onVisableChange(true);
    }
  }, 200);
  const hoverCloseDialog = lodash.debounce(() => {
   
   
    //移开关闭dialog
    if (type == 'hover' && showDialog == true) {
   
   
      setShowDialog(false);
      onVisableChange && onVisableChange(false);
    }
  }, 200);
  const dialogStyle = useMemo(() => {
   
   
    let alignStyle: alignStyle = {
   
   };
    if (align == 'bottom') {
   
   
    } else if (align == 'top') {
   
   
      alignStyle.bottom = showBtnSize.height + 'px';
    } else if (align == 'right') {
   
   
      alignStyle.left = showBtnSize.width + 'px';
      alignStyle.bottom = Number(showBtnSize.height) / 2 + 'px';
    } else if (align == 'left') {
   
   
      alignStyle.right = showBtnSize.width + 'px';
      alignStyle.bottom = Number(showBtnSize.height) / 2 + 'px';
    }
    return {
   
   
      width: showDialog ? `${
     
     dialogWidth}px` : '0px',
      height: showDialog ? '' : '0px',
      opacity: showDialog ? 1 : 0,
      ...alignStyle,
    };
  }, [content, showDialog, propsVisiable, showBtnSize]);
  return (
    <div className="popover-card">
      <div
        className="open-container"
        onMouseEnter={
   
   () => hoverOpenDialog()}
        onMouseLeave={
   
   () => hoverCloseDialog()}
      >
        <div className="show-btn" onClick={
   
   (e) => clickToggleDialog(e)} ref={
   
   showBtnRef as any}>
          {
   
   children}
        </div>
        <div
          className="pop-dialog"
          style={
   
   dialogStyle}
          onClick={
   
   (e) => e.stopPropagation()}
          onMouseEnter={
   
   () => hoverOpenDialog()}
          onMouseLeave={
   
   () => hoverCloseDialog()}
        >
          {
   
   content}
        </div>
      </div>
    </div>
  );
};

export default memo(Popover);

有任何问题或建议欢迎留言,此文为展示记录性博客。

目录
相关文章
|
JavaScript
vue可拖拽悬浮按钮组件
vue封装一个可拖拽,贴边吸附的悬浮按钮组件。
2043 0
|
4月前
|
JavaScript API 容器
Vue3气泡卡片(Popover)
这是一个基于Vue的气泡卡片组件(Popover)介绍,提供了在线预览链接及详细API参数说明,包括maxWidth、title、content等,并支持自定义样式。
225 0
Vue3气泡卡片(Popover)
【1】ElementUI 组件实际应用===》按钮的使用
这篇文章详细介绍了Element UI库中的按钮组件的使用方法,包括基础用法、禁用状态、文字按钮、图标按钮、按钮组、加载中状态、不同尺寸的按钮以及按钮的属性说明。文章通过实例代码展示了如何定义按钮样式、添加图标、设置按钮尺寸和类型,并解释了如何绑定方法到按钮以执行操作。
|
4月前
|
JavaScript
在Vue中使用Swiper轮播图、同时解决点击轮播图左右切换按钮不生效的问题、同时将轮播图抽离出为一个公共组件
这篇文章介绍了在Vue中如何使用Swiper插件创建轮播图,解决Swiper左右切换按钮不生效的问题,并展示了如何将Swiper轮播图抽离成一个可复用的公共组件,同时提供了详细的安装、配置和优化建议。
在Vue中使用Swiper轮播图、同时解决点击轮播图左右切换按钮不生效的问题、同时将轮播图抽离出为一个公共组件
|
7月前
|
JavaScript 定位技术 API
OpenLayers入门-第二篇、在vue3中使用elementplus制作图层控件,图层切换,显示隐藏,图层排序
OpenLayers入门-第二篇、在vue3中使用elementplus制作图层控件,图层切换,显示隐藏,图层排序
178 1
|
7月前
|
移动开发 小程序 API
uniapp组件库Popup 弹出层 的使用方法
uniapp组件库Popup 弹出层 的使用方法
556 1
|
前端开发
Concis组件库封装——CheckBox多选框/多选组
Concis组件库封装——CheckBox多选框/多选组组件封装
121 1
Concis组件库封装——CheckBox多选框/多选组
|
前端开发 JavaScript API
Concis组件库封装——TreeView树形控件
Concis组件库封装——TreeView树形控件组件封装
138 1
Concis组件库封装——TreeView树形控件
antd组件库封装51-升级button样式1
antd组件库封装51-升级button样式1
89 0
antd组件库封装51-升级button样式1
antd组件库封装52-升级button样式2
antd组件库封装52-升级button样式2
55 0
antd组件库封装52-升级button样式2