Antd组件的二次封装

react antd 是一个基于 react 的 UI 组件库,提供了丰富的组件和设计规范。但是,有时候我们需要对它的组件进行二次封装,以适应不同的业务场景和需求。

一、二次封装的目的

1、增加或修改组件的功能和样式

2、统一组件的使用方式和风格

3、简化组件的调用和传参

二、二次封装的方法

1、创建一个自定义组件,引入 antd 的组件

2、定义自定义组件的类型和属性,可以继承或扩展 antd 组件的类型和属性

3、在自定义组件中实现自己的渲染逻辑,可以使用 antd 组件提供的 API 和属性

4、将自定义组件需要传递给 antd 组件的属性,通过 rest 参数或解构赋值的方式传递给 antd 组件

三、示例:基于 Antd 的 DatePicker 组件的二次封装
1、实现的功能:

(1)预设 昨天、今天、上周、本周、上月、本月 时间范围快捷选择

(2)设置只能选择某天数范围之内的日期,默认无限制

(3)设置某天以后的时间不能选择,默认今天

2、代码实现

(1)封装组件:RangeDatePicker.js

import React, { useState } from 'react'
import { DatePicker } from 'antd'
import 'moment/locale/zh-cn'
import locale from 'antd/lib/date-picker/locale/zh_CN'
import moment from 'moment'
import { cloneDeep } from 'lodash'

const RangeDatePicker = ({
                             value, // 日期
                             onChange, // 时间发生变化的回调,发生在用户选择时间时
                             showTime = false, // 是否增加时间选择功能(时分秒)
                             limitDay = 0, // 只能选择limitDay天数范围之内的日期,默认无限制
                             endOfDay = moment().endOf('day'), // endOfDay以后的时间不能选择,默认今天
                             ...rest // 其他参数
                         }) => {
    const { RangePicker } = DatePicker

    const startOfDay = moment()
        .subtract(limitDay, 'days')
        .endOf('day') // 今天之前limitDay天

    const [selectDate, setSelectDate] = useState([startOfDay, endOfDay])
    const [selectvalue, setSelectValue] = useState([startOfDay, endOfDay])

    // 不可选择的日期
    const disabledTaskDate = current => {
        let date = cloneDeep(selectDate)
        if (selectDate && selectDate?.length > 0 && limitDay > 0) {
            // 控制只能选择limitDay天数范围之内的日期
            let startOfStage = date?.[1]?.subtract(limitDay, 'days').endOf('day')
            let endOfStage = date?.[0]?.add(limitDay, 'days').endOf('day')
            if (endOfStage > endOfDay) {
                endOfStage = endOfDay
            }
            return current < startOfStage || current > endOfStage
        } else {
            // endOfDay以后的时间不能选择
            return current > endOfDay
        }
    }

    // 待选日期发生变化的回调
    const onDateChange = dates => {
        if (!dates || !dates?.length) return
        setSelectDate([cloneDeep(dates?.[0]), cloneDeep(dates?.[1])])
    }

    // 弹出日历和关闭日历的回调
    const onDateOpenChange = open => {
        if (open) {
            if (selectvalue && selectvalue?.length) return
            setSelectDate([])
        }
    }

    // 时间发生变化的回调
    const onPickerChange = value => {
        setSelectValue(value)
        onChange(value)
    }

    // 获取预设时间范围快捷选择
    const getRanges = () => {
        // 今天
        const toDayRange =
            moment().startOf('day') <= endOfDay
                ? { 今天: [moment().startOf('day'), moment().endOf('day')] }
                : {}
        // 本周
        const thisWeekRange =
            moment().startOf('week') <= endOfDay ? { 本周: [moment().startOf('week'), endOfDay] } : {}
        // 本月
        const thisMonthRange =
            moment().startOf('month') <= endOfDay ? { 本月: [moment().startOf('month'), endOfDay] } : {}

        return {
            // 昨天
            昨天: [
                moment()
                    .subtract(1, 'days')
                    .startOf('day'),
                moment()
                    .subtract(1, 'days')
                    .endOf('day'),
            ],
            // 今天
            ...toDayRange,
            // 上周
            上周: [
                moment(new Date())
                    .subtract(1, 'week')
                    .startOf('week'),
                moment(new Date())
                    .subtract(1, 'week')
                    .endOf('week'),
            ],
            // 本周
            ...thisWeekRange,
            // 上月
            上月: [
                moment(new Date())
                    .subtract(1, 'month')
                    .startOf('month'),
                moment(new Date())
                    .subtract(1, 'month')
                    .endOf('month'),
            ],
            // 本月
            ...thisMonthRange,
        }
    }

    return (
        <RangePicker
            locale={locale} // 国际化配置(汉化)
            getPopupContainer={triggerNode => triggerNode.parentNode} // 定义浮层的容器(解决选项框随页面滚动分离问题)
            showTime={
                showTime
                    ? {
                        hideDisabledOptions: true, // 隐藏禁止选择的选项
                        defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')], // 默认时间
                    }
                    : null
            }
            format={showTime ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD'} // 日期格式
            ranges={{
                ...getRanges(),
            }}
            value={value} // 日期
            onChange={onPickerChange} // 时间发生变化的回调
            disabledDate={disabledTaskDate} // 不可选择的日期
            onCalendarChange={onDateChange} // 待选日期发生变化的回调
            onOpenChange={onDateOpenChange} // 弹出日历和关闭日历的回调
            {...rest}
        />
    )
}

export default RangeDatePicker

(2)默认使用

import React from 'react';
import RangeDatePicker from "../custom-component/RangeDatePicker";
class GoodsInfo extends React.Component{
    constructor(props) {
        super(props);
    }

    render() {
        return (
            <>
                <RangeDatePicker onChange={()=>{}}></RangeDatePicker> //默认使用
            </>
        )

    }
}
export default GoodsInfo

效果:

(3)带时间选择功能

render() {
        return (
            <>
                <RangeDatePicker onChange={()=>{}} showTime={true}></RangeDatePicker> //带时间选择功能
            </>
        )
    }

效果:

(4)设置天数选择范围

render() {
        return (
            <>
                <RangeDatePicker onChange={()=>{}}  limitDay={7}></RangeDatePicker> //设置天数选择范围
            </>
        )
    }

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

上庸者-不服周

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值