当前位置:首页 > 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组件状态的方法 使用useState和useEffect钩子组合可以同步React组件的状态。useState用于声明状态变量,useEffect用于监听状态变化并执行副作用。 imp…

react如何重写alert

react如何重写alert

重写 React 中的 alert 方法 在 React 中,直接使用原生 alert 会破坏用户体验,通常需要自定义弹窗组件替代。以下是实现方法: 使用自定义弹窗组件 创建可复用的弹窗组件,替代原…

react如何编码参数

react如何编码参数

编码参数的方法 在React中,编码参数通常涉及URL查询参数或路由参数的编码和解码。以下是几种常见场景的处理方法: URL查询参数编码 使用encodeURIComponent对参数进行编码,避免…

react如何上传图片

react如何上传图片

使用input标签上传图片 在React中可以通过HTML的<input type="file">元素实现图片上传功能。创建一个受控组件来管理文件选择状态: function Image…

react如何使用ueditor

react如何使用ueditor

安装 UEditor 下载 UEditor 的官方版本,解压后将整个文件夹放入项目的 public 目录下。确保可以通过 URL 直接访问 UEditor 的资源文件,例如 public/uedito…

react如何知道更新

react如何知道更新

React 更新机制的核心原理 React 通过虚拟 DOM(Virtual DOM)和协调算法(Reconciliation)来确定何时以及如何更新界面。组件的状态(state)或属性(props)…