react+antd Anchor(锚点组件)通讯录字母索引实现

发布于:2025-07-04 ⋅ 阅读:(19) ⋅ 点赞:(0)

一、页面概述

本项目实现了一个美观、实用的通讯录页面,采用 React 框架,结合 Ant Design 组件库与 TailwindCSS 原子化样式,支持按字母分组展示联系人,并提供便捷的字母索引导航。页面设计现代,交互流畅,适用于各类需要联系人管理的 Web 应用。

二、功能特点

  1. 字母分组展示
    联系人自动按姓名首字母分组,分组标题悬浮吸顶,便于快速定位。
  2. 字母索引导航
    右侧集成 Ant Design Anchor 组件,点击字母可平滑滚动至对应分组,提升查找效率。
  3. 响应式布局
    页面采用 Flex 布局与 TailwindCSS,适配不同屏幕尺寸,移动端与桌面端均有良好体验。
  4. 美观的 UI 设计
    联系人卡片采用圆角、阴影、渐变背景等设计,整体风格简洁现代,支持主题色自定义。
  5. 交互细节优化
    支持悬浮高亮、点击反馈、分组吸顶等细节,提升用户操作的愉悦感。

三、技术亮点

  • React 组件化开发
    代码结构清晰,易于维护和扩展,支持数据动态加载与状态管理。
  • Ant Design Anchor 组件深度定制
    通过自定义样式和参数,完美融合 Antd Anchor 字母索引与自定义通讯录列表。
  • TailwindCSS 原子化样式
    快速开发高质量 UI,无需编写繁琐的 CSS,极大提升开发效率。
  • 平滑滚动与吸顶效果
    利用原生 scroll-behavior 和 CSS sticky,实现分组标题吸顶与平滑滚动,用户体验极佳。
  • 高可扩展性
    支持后续集成搜索、分组管理、联系人详情等功能,适合二次开发。

四、适用场景

  • 企业/组织内部通讯录管理系统
  • 社交类 App/Web 的联系人模块
  • 教育、医疗、政务等行业的人员名录展示
  • 需要字母索引导航的任意列表型数据页面
  • 需要快速查找、分组展示的用户信息管理后台

五、全部源码

import { useRef } from "react";
import { Anchor } from "antd";
import "antd/dist/reset.css";

// 示例数据
const contacts = [
  { name: "Alice", initial: "A" },
  { name: "Aaron", initial: "A" },
  { name: "Bob", initial: "B" },
  { name: "Bella", initial: "B" },
  { name: "Cindy", initial: "C" },
  { name: "David", initial: "D" },
  { name: "Eve", initial: "E" },
  { name: "Frank", initial: "F" },
  { name: "Grace", initial: "G" },
  { name: "Helen", initial: "H" },
  { name: "Ivy", initial: "I" },
  { name: "Jack", initial: "J" },
  { name: "Kathy", initial: "K" },
  { name: "Leo", initial: "L" },
  { name: "Mona", initial: "M" },
  { name: "Nina", initial: "N" },
  { name: "Oscar", initial: "O" },
  { name: "Paul", initial: "P" },
  { name: "Queen", initial: "Q" },
  { name: "Rose", initial: "R" },
  { name: "Sam", initial: "S" },
  { name: "Tom", initial: "T" },
  { name: "Uma", initial: "U" },
  { name: "Vera", initial: "V" },
  { name: "Will", initial: "W" },
  { name: "Xander", initial: "X" },
  { name: "Yuki", initial: "Y" },
  { name: "Zack", initial: "Z" },
];

// 分组
const grouped = contacts.reduce((acc, cur) => {
  acc[cur.initial] = acc[cur.initial] || [];
  acc[cur.initial].push(cur);
  return acc;
}, {});
const letters = Array.from({ length: 26 }, (_, i) =>
  String.fromCharCode(65 + i)
);

export default function ContactsAntd() {
  const listRef = useRef();

  // 生成Anchor的items
  const anchorItems = letters
    .filter((letter) => grouped[letter])
    .map((letter) => ({
      key: letter,
      href: `#${letter}`,
      title: letter,
    }));

  return (
    <>
      {/* 覆盖Antd Anchor字母索引栏padding-inline的全局样式 */}
      <style>{`
        :where(.css-dev-only-do-not-override-1rfzxih).ant-anchor-wrapper .ant-anchor .ant-anchor-link {
          padding-inline: 8px 0 !important;
          line-height: 14px;
        }
        :where(.css-dev-only-do-not-override-1rfzxih).ant-anchor-wrapper:not(.ant-anchor-wrapper-horizontal) .ant-anchor::before {
          border-inline-start: 2px solid rgb(239, 68, 68);
        }
          :where(.css-dev-only-do-not-override-1rfzxih).ant-anchor-wrapper .ant-anchor .ant-anchor-link-active>.ant-anchor-link-title {
            font-weight: bold;
          }
      `}</style>
      <div className="flex relative h-screen bg-gradient-to-br from-rose-100 to-white">
        {/* 通讯录列表 */}
        <div
          ref={listRef}
          className="flex-1 overflow-y-auto px-4 py-4"
          style={{ scrollBehavior: "smooth" }}
        >
          <h1 className="text-2xl font-bold mb-4 text-red-700 tracking-wide">
            通讯录
          </h1>
          {letters.map(
            (letter) =>
              grouped[letter] && (
                <div key={letter} id={letter}>
                  <div className="sticky top-0 z-10 text-red-600 font-bold px-2 py-1 rounded mt-2 mb-1 shadow-sm backdrop-blur bg-white/90">
                    {letter}
                  </div>
                  <div className="space-y-2 mb-4">
                    {grouped[letter].map((c) => (
                      <div
                        key={c.name}
                        className="flex items-center gap-3 px-4 py-2 bg-white rounded-xl shadow hover:bg-rose-50 transition cursor-pointer group border border-rose-100 hover:border-red-300"
                      >
                        <div
                          className={`w-10 h-10 flex items-center justify-center rounded-full text-white text-lg font-bold shadow bg-red-500 group-hover:bg-red-600`}
                        >
                          {c.name[0]}
                        </div>
                        <span className="text-gray-800 text-base font-medium group-hover:text-red-700 transition">
                          {c.name}
                        </span>
                      </div>
                    ))}
                  </div>
                </div>
              )
          )}
        </div>
        {/* 右侧字母索引栏(Antd Anchor) */}
        <div className="fixed right-1 top-1/2 -translate-y-1/2 z-20 flex flex-col items-center justify-center border-2 border-red-500 rounded-sm py-0 pr-1 bg-white border-l-0">
          <Anchor
            direction="vertical"
            items={anchorItems}
            getContainer={() => listRef.current}
            affix={false}
            showInkInFixed={true}
            style={{ background: "transparent" }}
          />
        </div>
      </div>
    </>
  );
}

注意

Anchor 锚点实现,如果通讯录组件使用在弹框组件内,点击锚点时,滚动条会出现异常,需要使用 getContainer 属性,指定锚点滚动容器,否则会默认滚动到页面顶部。

 react+antd Anchor(锚点组件)通讯录字母索引实现 - 高质量源码分享平台-免费下载各类网站源码与模板及前沿动态资讯


网站公告

今日签到

点亮在社区的每一天
去签到