React+TS前台项目实战(十七)-- 全局常用组件Dropdown封装

文章目录

  • 前言
  • Dropdown组件
    • [1. 功能分析](#1. 功能分析)
    • [2. 代码+详细注释](#2. 代码+详细注释)
    • [3. 使用方式](#3. 使用方式)
    • [4. 效果展示](#4. 效果展示)
  • 总结

前言

今天这篇主要讲全局Dropdown组件封装,可根据UI设计师要求自定义修改。


1. 功能分析

(1)通过position属性,可以控制下拉选项的位置

(2)通过传入width属性, 可以自定义下拉选项的宽度

(3)通过传入className属性, 可以自定义加载动画的样式

2. 代码+详细注释

c 复制代码
// @/components/Dropdown/index.tsx
import { useState } from 'react'
import classNames from "classnames";
import { DropDownContainer, DropDown } from './styled'
import Button from '@/Button'
// 组件的属性类型
type Options = {
  // 下拉选项的文本
  name: string
  // 下拉选项自定义类名
  value: string
}
// 组件的属性类型
type Props = {
  data: Options[]
  position?: string
  width?: string
  name: string
  className?: string
};
export default ({
  data,
  position,
  width,
  name,
}: Props) => {
  // 是否显示下拉选项
  const [showDropDown, setShowDropDown] = useState(false)
  // 下拉选项位置
  const dropdownPosition: string = position ?? 'left'
  // 下拉框宽度,默认100%
  const dropdownWidth: string = width ?? '100%'
  // 下拉选项点击事件
  const handlerItemClick = () => {
    setShowDropDown(false)
  }
  return (
    <>
      <DropDownContainer  className={classNames(className)}width={dropdownWidth} onMouseLeave={handlerItemClick}>
        <Button
          className="dropdown-button"
          onMouseOver={() => {
            setShowDropDown(true)
          }}
        >
          <div className={classNames('dropdown-button-content')}>
            <div
              className={classNames('dropdown-button-title')}
              style={{
                textTransform: 'uppercase',
              }}
            >
              {name}
            </div>
            <div className={classNames('dropdown-arrow')}>&gt;</div>
          </div>
        </Button>
        {showDropDown && (
          <DropDown position={dropdownPosition} onMouseLeave={ handlerItemClick }>
            <>
              {data.map((item, index) => (
                <>
                  <Button key={index} className={classNames('dropdown-item')} onClick={ handlerItemClick }>
                    {item.name}
                  </Button>
                  {index !== data.length - 1 && <div className={classNames('dropdown-separate')}></div>}
                </>
              ))}
            </>
          </DropDown>
        )}
      </DropDownContainer>
    </>
  )
}


------------------------------------------------------------------------------
// @/components/Dropdown/styled.tsx
import styled from "styled-components";
interface DropDownProps {
  width: string;
}
interface DropDownItemProps {
  position: string;
}
export const DropDownContainer = styled.div<DropDownProps>`
  display: flex;
  align-items: center;
  height: 100%;
  margin-top: 1px;
  padding: 10px 0;
  position: relative;
  width: ${({ width }) => width};
  @media (max-width: 750px) {
    margin-right: 0;
  }
  color: ${(props) => props.theme.primary};
  .dropdown-button-content {
    display: flex;
    align-items: center;
    .dropdown-arrow {
      font-size: 18px;
      margin-left: 4px;
      transform: rotate(90deg);
    }
  }
  &:hover {
    .dropdown-arrow {
      transform: rotate(270deg);
    }
  }
`;
export const DropDown = styled.div<DropDownItemProps>`
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  min-width: 130px;
  color: #000;
  background: #fff;
  border-radius: 5px;
  box-shadow: 0 2px 4px 0 rgb(0 0 0 / 50%);
  z-index: 1000;
  position: absolute;
  top: 45px;
  left: ${({ position }) => (position === "left" ? 0 : "auto")};
  right: ${({ position }) => (position === "right" ? 0 : "auto")};
  .dropdown-item {
    display: flex;
    align-items: center;
    width: 94%;
    height: 33px;
    margin: 3px 3% 0;
    padding: 0 3%;
    font-size: 12px;
    white-space: nowrap;
    border-radius: 3px;
    cursor: pointer;
    &:hover {
      background: #f1f1f1;
      color: var(--cd-primary-color);
    }
  }
  .dropdown-separate {
    width: 88%;
    height: 0.5px;
    border: solid 0.5px #c3c3c3;
    margin: 0 6%;
  }
`;

3. 使用方式

c 复制代码
// 引入组件
import Dropdown from '@/components/Dropdown'
// 使用
<Dropdown
  data={[
    { name: '下拉选项111111', value: '434432' },
    { name: '下拉选项222222', value: '434432' },
    { name: '下拉选项333333', value: '434432' },
 ]}
 position="left"
 width="100px"
 name="dropdown"
/>

4. 效果展示

(1)左对齐

(2)右对齐


总结

下一篇讲【高阶渲染劫持组件封装】。关注本栏目,将实时更新。

相关推荐
子兮曰1 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰1 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万1 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝1 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋1 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁1 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95271 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大1 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师1 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学1 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端