uniapp 日历组件 uni-datetime-picker

背景:

App端需要日历组件,选择年月日,或者年月日时分秒。找到了两种组件,如下:

方式一:

DCloud插件市场的uni-datetime-picker组件,设置为日期时间选择器【datetimerange】,或者日期选择器【daterange】

<uni-datetime-picker

v-model="timeData"

type="datetimerange"

rangeSeparator="至"

:start="minDate"

:end="maxDate"

@change="maskChange"

@maskClick="maskClick"

/>

方式二:

uniapp基础组件的picker组件,设置为日期选择器 mode="date"

<picker

mode="date"

:value="date"

:start="startDate"

:end="endDate"

@change="bindDateChange">

<view class="uni-input">{{date}}</view>

</picker>

插件市场有插件uni-datetime-picker,uniapp内置组件有picker组件。

一、插件市场uni-datetime-picker组件

效果展示:【由两部分组成:一组件,二点击组件的弹框】

日期选择器:

设置type为:daterange 或者 datetimerange

javascript 复制代码
<uni-datetime-picker 
v-model="timeData" 
type="datetimerange" 
rangeSeparator="至" 
:start="minDate"
:end="maxDate" 
@change="maskChange" 
@maskClick="maskClick"
 />

js逻辑层:

javascript 复制代码
<script>
export default {
    data() {
       return {
        timeData: [],
        minDate: '',
        maxDate: '',
    },
    methods:{
        formatTime(time, format = "YY-MM-DD hh:mm:ss") {
            const args = {
                y: time.getFullYear(),
                M: time.getMonth() + 1,
                d: time.getDate(),
                h: time.getHours(),
                m: time.getMinutes(),
                s: time.getSeconds(),
            };
            for (const key in args) {
                const value = args[key];
                if (value < 10) args[key] = "0" + value;
            }
            const dateStr =
                args.y +
                "-" +
                args.M +
                "-" +
                args.d +
                " " +
                args.h +
                ":" +
                args.m +
                ":" +
                args.s;
            return dateStr;
        },
        maskChange(e) {
            this.timeData = e
        },
        maskClick() {
        },
    },
    created() {
        const maxDate = this.formatTime(new Date(Date.now()))
        const minDate1 = this.formatTime(new Date(Date.now() - 8.64e7))
        const minDate7 = this.formatTime(new Date(Date.now() - 8.64e7 * 7))
        this.minDate = minDate7
        this.maxDate = maxDate
        this.timeData = [minDate1, maxDate]
    },
}

插件市场官网:点击跳转

下载插件市场的插件,可以通过HBuilder下载,或者下载zip然后导入项目文件夹uni_modules

二、uniapp内置组件

效果展示:

日期选择器:

javascript 复制代码
<picker 
  mode="date" 
  :value="date" 
  :start="minDate" 
  :end="maxDate" 
  @change="bindDateChange">
    <view class="uni-input">{{date}}</view>
</picker>

js逻辑层:

javascript 复制代码
<script>
export default {
    data() {
        const currentDate = this.getDate({
            format: true
        })
        return {
            title: 'picker',
            array: ['中国', '美国', '巴西', '日本'],
            index: 0,
            date: currentDate,
            time: '12:01'
        }
    },
    computed: {
        minDate() {
            return this.getDate('start');
        },
        maxDate() {
            return this.getDate('end');
        }
    },
    methods: {
        bindPickerChange: function(e) {
            console.log('picker发送选择改变,携带值为', e.detail.value)
            this.index = e.detail.value
        },
        bindDateChange: function(e) {
            this.date = e.detail.value
        },
        bindTimeChange: function(e) {
            this.time = e.detail.value
        },
        getDate(type) {
            const date = new Date();
            let year = date.getFullYear();
            let month = date.getMonth() + 1;
            let day = date.getDate();

            if (type === 'start') {
                year = year - 10;
            } else if (type === 'end') {
                year = year + 10;
            }
            month = month > 9 ? month : '0' + month;
            day = day > 9 ? day : '0' + day;
            return `${year}-${month}-${day}`;
        }
    }
}
</script>

uniapp组件官网链接:点击跳转

三、自行封装一个日历选择器

背景:

以上两种组件在H5端或者Android端组件的形式有所差异,可根据实际情况进行调整。

以下是自行封装了一个名为MyCalender的组件,组件只能选择具体的某一天。封装它的意图是想要弹出框尽量小,或者日历选择区域尽量小。

效果展示:

封装组件思路:

日期选择器只能选择一天。弹框根据实时日期渲染当月的总天数。大于当前日期的不可选并有提示信息,只能选择小于等于当前日期。

封装自定义组件:

javascript 复制代码
<template>
    <view class="MyCalender">
        <view class="inputBox" @click='toggle()'>
            <u-input :readonly="true" style="pointer-events:none" v-model="inputValue" :placeholder="'请选择一个时间'"
                suffixIcon="arrow-down" :clearable="true">
                <!-- <u--text text="视频回放日期:" slot="prefix" margin="0 3px 0 0" type="tips"></u--text> -->
            </u-input>
        </view>
        <!-- <view class="calenderBox" v-if="isOpen">
            <view class="calender_item" v-for="(item, index) in timeCalender" :key="index" @click="clickCalenderI(item)"
                :class="item === currentD ? 'active' : ''">
                <view class="calender_item_inner" :class="item > currentDStyle ? 'disabled' : ''">
                    {{ item }}
                </view>
            </view>
        </view> -->
        <u-popup mode="bottom" :round="20" :show="showPop" :closeOnClickOverlay="false" @close="handlePopup(false)"
            :closeable="true">
            <view class="pop-title">回放日期</view>
            <view class="calenderBox">
                <view class="calender_item" v-for="(item, index) in timeCalender" :key="index"
                    @click="clickCalenderI(item)" :class="item === currentD ? 'active' : ''">
                    <view class="calender_item_inner" :class="item > currentDStyle ? 'disabled' : ''">
                        {{ item }}
                    </view>
                </view>
            </view>
            <view class="pop-footer" @click="toggle"><u-button text="点我关闭" type="primary"></u-button></view>
        </u-popup>
    </view>
</template>
<script>
export default {
    name: "MyCalender",
    props: {
        defaultTime: {
            type: String,
            default: ''
        },
        timeArr: {
            type: Number,
            default: 30,
        }
    },
    data() {
        return {
            showPop: false,
            clickData: '',
            inputValue: '',
            isOpen: false,
            timeCalender: 0,
            currentD: 0,
            currentDStyle: 0,
        }
    },
    methods: {
        handlePopup(state) {
            this.showPop = state;
        },
        toggle() {
            console.log('toggle');
            this.showPop = !this.showPop
        },
        handleOpenOption(data) {
            console.log('handleOpenOption', data);
            this.isOpen = !this.isOpen
        },
        clickCalenderI(item) {
            console.log('clickCalenderI', item);
            this.currentD = item
            //根据第几天得出日期
            const whichData = new Date(new Date().getFullYear(), new Date().getMonth(), item)
            this.clickData = whichData
            if (this.clickData > new Date()) {
                this.clickData = new Date()
                this.currentD = this.clickData.getDate()
                uni.showToast({
                    icon: 'none',
                    title: `请重新选择日期,不可大于今日${this.currentD}号`,
                })
            } else {
                this.clickData = this.clickData
            }
            const whichData_String = this.clickData.getFullYear() + '-' + (this.clickData.getMonth() + 1) + '-' + this.clickData.getDate()
            this.inputValue = whichData_String
            this.$emit('clickCalenderI', this.inputValue)
        }
    },
    created() {
        //timeCalender
        const currentDate = new Date();
        const currentY = currentDate.getFullYear();
        const currentM = currentDate.getMonth() + 1;
        const currentD = currentDate.getDate();
        const days = new Date(currentY, currentM, 0).getDate();
        console.log('days', days);
        this.timeCalender = days;
        this.currentDStyle = currentD
    },
    watch: {
        defaultTime: {
            handler(val) {
                if (val && val.split(' ').length) {
                    this.inputValue = val.split(' ')[0]
                }
            },
            immediate: true,
            deep: true
        }
    }
}
</script>
<style lang="scss" scoped>
.MyCalender {
    max-width: 80%;
    height: 100%;
    box-sizing: border-box;
    // padding: 0px 10px;
    overflow: hidden;
    background-color: #fff;
    display: flex;
    align-items: center;

    .inputBox {
        width: 100%;
    }

    .calenderBox {
        width: auto;
        height: 30vh;
        display: flex;
        flex-direction: row;
        flex-wrap: wrap;
        overflow-x: scroll;
        box-sizing: border-box;
        padding: 20rpx 0rpx 20rpx 20rpx;

        .active {
            background-color: #3670EB !important;
        }

        .disabled {
            color: #ccd5e0 !important;
        }

        .calender_item {
            width: 60rpx;
            height: 60rpx;
            background-color: #a9a2a2;
            border-radius: 50%;
            margin-right: 10px;
            box-sizing: border-box;
            padding: 20px;
            display: flex;
            justify-content: center;
            align-items: center;
        }
    }
}
</style>
<style lang="scss">
.pop-title {
    text-align: center;
    font-size: larger;
}

.pop-container {
    height: 30vh;
    overflow-x: hidden;
    overflow-y: auto;
}
</style>

使用自定义的组件:

<MyCalender :defaultTime="maxDate" @clickCalenderI="clickCalenderI"></MyCalender>
//vue2

clickCalenderI(item) {

console.log('clickCalenderI', item);

this.timeData = [`{item} 00:00:00\`, \`{item} 23:59:59`]

},

this.maxDate = this.formatTime(new Date(Date.now()))

formatTime(time, format = "YY-MM-DD hh:mm:ss") {

const args = {

y: time.getFullYear(),

M: time.getMonth() + 1,

d: time.getDate(),

h: time.getHours(),

m: time.getMinutes(),

s: time.getSeconds(),

};

for (const key in args) {

const value = args[key];

if (value < 10) args[key] = "0" + value;

}

const dateStr =

args.y +

"-" +

args.M +

"-" +

args.d +

" " +

args.h +

":" +

args.m +

":" +

args.s;

return dateStr;

},

写到这儿。。。我们就实现了三种uniapp选择日期的方式,根据实际情况自行选择。。。

相关推荐
不知名的前端专家4 小时前
uniapp 安卓FTP上传下载操作原生插件
android·uni-app
向下的大树5 小时前
npm 最新镜像,命令导致下载错误
前端·npm·node.js
宁雨桥5 小时前
Service Worker:前端离线化与性能优化的核心技术
前端·性能优化
IT_陈寒5 小时前
SpringBoot实战:这5个隐藏技巧让我开发效率提升200%,90%的人都不知道!
前端·人工智能·后端
ObjectX前端实验室5 小时前
【图形编辑器架构】节点树与渲染树的双向绑定原理
前端·计算机图形学·图形学
excel5 小时前
Vue2 与 Vue3 生命周期详解与对比
前端
一只猪皮怪56 小时前
React 18 前端最佳实践技术栈清单(2025版)
前端·react.js·前端框架
Misnice6 小时前
React渲染超大的字符串
前端·javascript·react.js
天天向上的鹿茸6 小时前
用矩阵实现元素绕不定点旋转
前端·线性代数·矩阵