当前位置:首页 > React

react popover实现

2026-01-26 16:57:12React

使用 React Portals 实现 Popover

React Portals 提供了一种将子节点渲染到父组件 DOM 层次结构之外的 DOM 节点的方式,适合实现弹出层。

import React, { useState, useRef } from 'react';
import ReactDOM from 'react-dom';

function Popover({ content, children }) {
  const [isOpen, setIsOpen] = useState(false);
  const triggerRef = useRef(null);

  const handleClick = () => setIsOpen(!isOpen);

  return (
    <>
      <span ref={triggerRef} onClick={handleClick}>
        {children}
      </span>
      {isOpen &&
        ReactDOM.createPortal(
          <div className="popover">
            <div className="popover-content">{content}</div>
          </div>,
          document.body
        )}
    </>
  );
}

使用 CSS 定位 Popover

通过获取触发元素的位置信息,可以精确控制 Popover 的显示位置。

react popover实现

function Popover({ content, children }) {
  const [isOpen, setIsOpen] = useState(false);
  const [position, setPosition] = useState({ top: 0, left: 0 });
  const triggerRef = useRef(null);

  const handleClick = () => {
    if (triggerRef.current) {
      const rect = triggerRef.current.getBoundingClientRect();
      setPosition({
        top: rect.bottom + window.scrollY,
        left: rect.left + window.scrollX
      });
    }
    setIsOpen(!isOpen);
  };

  return (
    <>
      <span ref={triggerRef} onClick={handleClick}>
        {children}
      </span>
      {isOpen && (
        <div
          className="popover"
          style={{
            position: 'absolute',
            top: `${position.top}px`,
            left: `${position.left}px`
          }}
        >
          {content}
        </div>
      )}
    </>
  );
}

添加关闭行为和动画效果

实现点击外部关闭和简单的淡入淡出动画效果。

react popover实现

function Popover({ content, children }) {
  const [isOpen, setIsOpen] = useState(false);
  const popoverRef = useRef(null);

  useEffect(() => {
    const handleClickOutside = (event) => {
      if (popoverRef.current && !popoverRef.current.contains(event.target)) {
        setIsOpen(false);
      }
    };
    document.addEventListener('mousedown', handleClickOutside);
    return () => document.removeEventListener('mousedown', handleClickOutside);
  }, []);

  return (
    <div className="popover-container">
      <span onClick={() => setIsOpen(true)}>{children}</span>
      <div
        ref={popoverRef}
        className={`popover ${isOpen ? 'fade-in' : 'fade-out'}`}
      >
        {content}
      </div>
    </div>
  );
}

使用第三方库实现

React 社区有许多成熟的 Popover 组件库可以直接使用。

import { Popover } from 'react-tiny-popover';

function Example() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <Popover
      isOpen={isOpen}
      positions={['top', 'bottom', 'left', 'right']}
      content={<div>Popover Content</div>}
    >
      <button onClick={() => setIsOpen(!isOpen)}>
        Toggle Popover
      </button>
    </Popover>
  );
}

样式基础

基本的 Popover 样式可以这样定义:

.popover {
  position: absolute;
  background: white;
  border: 1px solid #ddd;
  border-radius: 4px;
  padding: 10px;
  box-shadow: 0 2px 10px rgba(0,0,0,0.1);
  z-index: 1000;
}

.fade-in {
  opacity: 1;
  transition: opacity 0.2s ease-in;
}

.fade-out {
  opacity: 0;
  transition: opacity 0.2s ease-out;
}

标签: reactpopover
分享给朋友:

相关文章

react如何开发组件

react如何开发组件

React 组件开发基础 React 组件分为函数组件和类组件两种形式。函数组件是现代 React 开发的主流方式,结合 Hooks 可以实现完整功能。 函数组件示例: function Gree…

如何react页面

如何react页面

创建 React 页面 使用 create-react-app 快速初始化项目: npx create-react-app my-app cd my-app npm start 基础页面结构 在 s…

react 如何分页

react 如何分页

分页实现方法 在React中实现分页功能可以通过多种方式完成,具体取决于数据来源(如API或本地数据)和UI库的选择。以下是常见的实现方法: 使用本地数据分页 对于存储在组件状态或Context中…

如何创建react

如何创建react

创建React项目的步骤 使用Create React App工具快速搭建React项目。确保已安装Node.js(版本需≥14.0.0)和npm(版本需≥5.6)。 打开终端或命令行工具,运行以下…

react如何卸载

react如何卸载

卸载 React 项目或依赖 如果需要完全卸载 React 项目或相关依赖,可以按照以下步骤操作: 删除项目文件夹 直接删除整个项目文件夹是最彻底的方式。确保已备份重要代码或配置文件。 卸载全局安…

react 如何循环

react 如何循环

循环渲染列表 在React中,循环渲染列表通常使用map方法。map可以遍历数组并返回一个新的React元素数组。 const items = ['Apple', 'Banana', 'Orange…