• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

vue3日历时间 vite + vue3 日历时间

武飞扬头像
ღ_2333
帮助1

vite vue3日历时间

#vue3 Calendar组件 日历组件 选择vite vue3

https://v3.cn.vuejs.org/guide/introduction.html
https://youzan.github.io/vant/#/zh-CN/home
https://vitejs.cn/

import { createApp } from 'vue'
import { Button,  Icon,  Overlay,  Picker } from 'vant'

createApp(App)
.use(Button)
.use(Icon)
.use(Overlay)
.use(Picker)
.mount('#app')
//   vite.config.js 
import { defineConfig } from 'vite'
import styleImport, { VantResolve } from 'vite-plugin-style-import'

export default defineConfig({
  plugins: [
      styleImport({ resolves: [VantResolve()] })
  ]
})
/**
     "vant": "^3.4.7",
     "vue": "^3.2.25",
     "sass": "^1.49.9",
     "vite": "^2.8.0",
     "vite-plugin-style-import": "1.4.1",
     "autoprefixer": "^10.4.4",
     "postcss-pxtorem": "^6.0.0"
*/
//  这里用了 postcss-pxtorem 对px进行rem转换,如果您没有用 postcss-pxtorem,还得需要您自己修改样式
/* *
     postcss.config.js
     'postcss-pxtorem': {
            rootValue: 37.5,
            propList: ['*'],
            unitPrecision: 5
        }
*/ 
学新通
<template>
    <section id="Calendar" v-cloak>
        <van-overlay :show="arise" @click="handleClose">
            <div class="calendar-view">
                <div class="container" @click.stop>
                    <div class="display-flex align-items-center justify-content-space-between">
                        <div class="calendar-top-l display-flex align-items-center" @click.stop="handlePreNextY(-1)">
                            <van-icon class="calendar-top-left mr10" name="arrow-left" />
                            <div class="m">{{ MonthChineseAndEnglish[month - 1].en_ab }}</div>
                            <div class="y">{{ year }}</div>
                            <van-icon class="calendar-top-right ml10" name="arrow" @click.stop="handlePreNextY(1)"></van-icon>
                        </div>
                        <div class="calendar-top-r">
                            <van-icon class="calendar-top-left mr20" name="arrow-left" @click.stop="handlePreNextM(-1)" />
                            <van-icon class="calendar-top-right" name="arrow" @click.stop="handlePreNextM(1)" />
                        </div>
                    </div>
                    <div>
                        <ul class="week"><li v-for="i of Week" :key="i" class="week-op">{{ i }}</li></ul>
                    </div>
                    <div class="date-g-v">
                        <ul class="date-grid">
                            <li v-for="(i, index) of currentCalendarFullDays"
                                :key="i.key"
                                class="date-grid-list"
                                @click.stop="handleSelymd(i, index)"
                                :class="{ 'selBg': i.active }"
                            >
                                <p class="date-view"
                                   :class="{ 'date-day-current': (i.where === 'current' && year === nDate.getFullYear() && month === nDate.getMonth()   1 && Number(i.day) === nDate.getDate()) || i.active,
                                             'preDay': i.where === 'pre',
                                             'nextDay': i.where === 'next'
                                }">
                                    {{ i.zh_ch }}
                                    <span class="date-view-ab"
                                          :class="{ 'date-day-current': (i.where === 'current' && year === nDate.getFullYear() && month === nDate.getMonth()   1 && Number(i.day) === nDate.getDate()) || i.active,
                                             'preDay': i.where === 'pre',
                                             'nextDay': i.where === 'next'
                                }">{{ i.en_day_ab }}</span></p>
                            </li>
                        </ul>
                    </div>
                    <div class="time">
                        <div><p class="time-title">Time</p></div>
                        <div class="w-time-picker">
                            <van-picker @change="handlePicker" :show-toolbar="false" :item-height="wWidth ? '50px' : '26px'
" :columns="columns" />
                        </div>
                    </div>
                    <div class="time-confirm" @click.stop="handleConfirm">
                        <van-button type="warning" block>Confirm</van-button>
                    </div>
                </div>
            </div>
        </van-overlay>
    </section>
</template>
学新通
<script setup>

    import { defineEmits, defineProps, nextTick, reactive, ref, toRefs, watch } from 'vue'

    const props = defineProps({
        arise: {
            type: Boolean,
            default: false
        },
        ymdhms: {
            type: Object,
            default: {
                // ymd: 2022/04/17
                // hms: 00:00:00
            }
        }
    })
    const emits = defineEmits(['update:arise', 'giveMe'])

    const date = props.ymdhms.ymd ? ref(new Date(props.ymdhms.ymd)) : ref(new Date()) // 传入时间 || 当前时间
    const nDate = new Date()
    const ymd = reactive({
        year: date.value.getFullYear(), // 年
        month: date.value.getMonth()   1, // 月
        day: date.value.getDate() // 日
    })
    const wWidth = window.screen.width >= 768
    const Week = reactive(['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT']) // 星期 (周日 - 周六)
    const MonthChineseAndEnglish = ref([ // 中英文月份
        {
            zh_ch: '一月',
            en_us: 'January',
            en_ab: 'Jan.',
            str_num: '01'
        },
        {
            zh_ch: '二月',
            en_us: 'February',
            en_ab: 'Feb.',
            str_num: '02'
        },
        {
            zh_ch: '三月',
            en_us: 'March',
            en_ab: 'Mar.',
            str_num: '03'
        },
        {
            zh_ch: '四月',
            en_us: 'April',
            en_ab: 'Apr.',
            str_num: '04'
        },
        {
            zh_ch: '五月',
            en_us: 'May',
            en_ab: 'May.',
            str_num: '05'
        },
        {
            zh_ch: '六月',
            en_us: 'June',
            en_ab: 'Jun.',
            str_num: '06'
        },
        {
            zh_ch: '七月',
            en_us: 'July',
            en_ab: 'Jul.',
            str_num: '07'
        },
        {
            zh_ch: '八月',
            en_us: 'August',
            en_ab: 'Aug.',
            str_num: '08'
        },
        {
            zh_ch: '九月',
            en_us: 'September',
            en_ab: 'Sept.',
            str_num: '09'
        },
        {
            zh_ch: '十月',
            en_us: 'October',
            en_ab: 'Oct.',
            str_num: '10'
        },
        {
            zh_ch: '十一月',
            en_us: 'November',
            en_ab: 'Nov.',
            str_num: '11'
        },
        {
            zh_ch: '十二月',
            en_us: 'December',
            en_ab: 'Dec.',
            str_num: '12'
        }
    ])
    const monthList = ref([31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]) // 1 3 5 7 8 10 12 (31) 4 6 9 11 (30) 2 (28, 29)
    const monthSize = ref(0) // 天数
    const firstDay = ref(null) // 当月第一天是星期几
    const lastDay = ref(null) // 当月最后一天是星期几
    const preDay = ref(0) // 当月一号前面剩余天数
    const nextDay = ref(0) // 当月一号前面剩余天数
    const columns = reactive([ // 选择时间
        {
            values: ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23'],
            defaultIndex: 9
        },
        {
            values: ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59'],
            defaultIndex: 9
        },
        {
            values: ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59'],
            defaultIndex: 9
        }
    ])
    const currentCalendarFullDays = ref([]) // 日期list
    const throwToYou = reactive({ date: { yr: '', m: '', d: '', hr: '', min: '', s: '' } }) // 传递给父组件

    /**
     * oopsIsALeapYear
     * 公历闰年判定遵循的规律为:四年一闰、百年不闰、400年再闰。
     * 公历闰年的精确计算方法:普通年能被四整除且不能被100整除的为闰年。
     * 世纪年能被400整除的是闰年,如2000年是闰年,1900年不是闰年。
     * 对于数值很大的年份,如果这年能整除3200并且能整除172800则是闰年。
     * return @type { Boolean } true 是闰年
     */
    function oopsIsALeapYear(y) {
        return (y % 4 === 0 && y % 100 !== 0) || y % 400 === 0
    }

    if (oopsIsALeapYear(ymd.year)) { // 是闰年
        monthList.value[1] = 29 // 二月是29天
    }

    function handleLastMonthSize () {
        monthSize.value = monthList.value[ymd.month - 1] // 当月天数
        firstDay.value = new Date(`${ ymd.year }/${ ymd.month }/01`).getDay() // 当月第一天是星期几
        preDay.value = firstDay.value === 7 ? 0 : firstDay.value // 当月1号前面上月剩余天数
        return ymd.month - 1 === 0 ? 31 : monthList.value[ymd.month - 2] // 上月天数大小(这个月是1月的话上个月就是12月共有31天)
    }

    function handleNextMonthSize() {
        monthSize.value = monthList.value[ymd.month - 1] // 当月天数
        lastDay.value = new Date(`${ ymd.year }/${ ymd.month }/${ monthSize.value }`).getDay() // 当月最后一天是星期几
        nextDay.value = lastDay === 7 ? 6 : 6 - lastDay.value // 下月天数, 如果最后一天是星期天则下月天数为6
    }


    /**
     *  英文日期缩写
     *  1st 21st 31st
     *  2nd 22nd
     *  3rd 23rd
     *  4th 5th 6th 7th 8th 9th 10th 11th
     *  12th 13th 14th 15th 16th 17th 18th 19th 20th
     *  24th 25th 26th 27th 28th 29th 30th
     */
    function handleDayAb(_day) {
        let day = String(_day),
            rDay = ''
        if (day === '01' || day === '21' || day === '31') {
            rDay = `st`
        } else if (day === '02' || day === '22') {
            rDay = `nd`
        } else if (day === '03' || day === '23') {
            rDay = `rd`
        } else {
            rDay = `th`
        }
        return rDay
    }


    function funcIsBA(where) {
        let yr = Number(ymd.year),
            m = Number(ymd.month)
        if (where === 'pre') {
            m -= 1
            if (m <= 0) {
                m = 12
                yr -= 1
            }
        } else if (where === 'next') {
            m  = 1
            if (m > 12) {
                m = 1
                yr  = 1
            }
        }
        return {
            yr, m
        }
    }


    function funcOrganizeDates(_Day, key, where) { // 处理日期
        let arr = []
        const pymd = throwToYou.date.yr ? `${ throwToYou.date.yr }/${ throwToYou.date.m }/${ throwToYou.date.d }` : props.ymdhms.ymd
        const isYmd = !!pymd
        const pymdArr = isYmd ? pymd.split('/') : []
        for (let i = 0; i < Number(_Day); i  ) {
            let day
            let day_len
            let act
            if (where === 'pre') {
                day = (Number(handleLastMonthSize()) - Number(_Day)   Number(i   1))
            } else {
                day = i   1
            }

            if (isYmd) { // 判断是否有传入的年月日设置选中状态
                const { yr, m } = funcIsBA(where)
                if (Number(pymdArr[0]) === Number(yr) &&
                    Number(pymdArr[1]) === Number(m) &&
                    where === 'pre' &&
                    Number(pymdArr[2]) === Number(day)) {
                    act = true
                } else if (Number(pymdArr[0]) === Number(yr) &&
                    Number(pymdArr[1]) === Number(m) &&
                    where === 'next' &&
                    Number(pymdArr[2]) === Number(day)) {
                    act = true
                } else {
                    act = Number(pymdArr[0]) === Number(ymd.year) && Number(pymdArr[1]) === Number(ymd.month) && Number(pymdArr[2]) === Number(day) && where === 'current'
                }
            } else {
                act = false
            }

            day_len = day.toString().length >= 2 ? day : `0${day}`

            arr.push({
                zh_ch: day_len,
                en_us: day_len   handleDayAb(day_len),
                en_day_ab: handleDayAb(day_len),
                key: day   key,
                where,
                day,
                active: act
            })
        }
        return arr
    }

    function funcDays() { // 整合 所有日期
        currentCalendarFullDays.value = []
        currentCalendarFullDays.value = [
            ...currentCalendarFullDays.value,
            ...funcOrganizeDates(preDay.value, 'pre_day', 'pre'), // preDay 当月前面日期
            ...funcOrganizeDates(monthSize.value, 'current_day', 'current'), // monthSize 当月日期
            ...funcOrganizeDates(nextDay.value, 'next_day', 'next') // nextDay 当月之后日期
        ]
    }


    function init() {
        // 初始化 传递给父组件的值
        if (!throwToYou.date.yr) {
            const MapYmd = new Map().set(0, 'yr').set(1, 'm').set(2, 'd')
            const MapHms = new Map().set(0, 'hr').set(1, 'min').set(2, 's')
            if (props.ymdhms.ymd) { // 是否传递了 ymdhms ymd
                let arrPYmd = props.ymdhms.ymd.split('/')
                for(let [key, value] of MapYmd.entries()){
                    throwToYou.date[value] = arrPYmd[key]
                }
            }
            if (props.ymdhms.hms) { // 是否传递了 ymdhms hms
                let arrPHms = props.ymdhms.hms.split(':')
                for (var i = 0; i < 3; i  ) { // 初始化时间展示
                    columns[i]['defaultIndex'] = columns[i].values.findIndex(i1 => i1 === arrPHms[i])
                }
                for(let [key, value] of MapHms.entries()){ // 初始化返回传入的时间
                    throwToYou.date[value] = arrPHms[key]
                }
            } else {
                for(let [key, value] of MapHms.entries()){ // 没有传递 设置成 09:09:09
                    throwToYou.date[value] = columns[key]['values'][9]
                }
            }
        }
        handleLastMonthSize()
        handleNextMonthSize()
        nextTick(() => {
            funcDays()
        })
    }
    init()

    function handleClose() { // 弹框关闭
        emits('update:arise', false)
    }

    function handleConfirm() { // 确认选择
        // console.log(throwToYou.date)
        emits('giveMe', throwToYou.date)
        handleClose()
    }

    function handlePreNextY(num) { // 年切换
        ymd.year  = num
        nextTick(() => {
            date.value = new Date(`${ymd.year}/${ymd.month}/${ymd.day}`)
        })
    }

    function handlePreNextM(num) { // 月份切换
        let m = ymd.month  = num
        if (m <= 0) {
            ymd.month = 12
            ymd.year  = num
        }
        if (m > 12) {
            ymd.month = 1
            ymd.year  = num
        }
        nextTick(() => {
            date.value = new Date(`${ymd.year}/${ymd.month}/${ymd.day}`)
        })
    }

    function handleSelymd(i, index) {
        let arr = currentCalendarFullDays.value
        currentCalendarFullDays.value = arr.map(item => {
            item.active = false
            return item
        })
        currentCalendarFullDays.value[index].active = true
        // date: {
        //         yr: '',
        //         m: '',
        //         d: '',
        //         hr: '',
        //         min: '',
        //         s: ''
        // }
        let d = i.zh_ch
        const { yr, m } = funcIsBA(i.where)
        const m1 = m.toString().length >= 2 ? m : `0${m}`
        throwToYou.date = {
            ...throwToYou.date,
            ...{ yr: String(yr), m: String(m1), d: String(d) }
        }
    }

    function handlePicker(val, index) {
        const MapHms = new Map().set(0, 'hr').set(1, 'min').set(2, 's')
        for(let [key, value] of MapHms.entries()){
            throwToYou.date[value] = val[key]
        }
    }

    watch([() => ymd.year, () => ymd.month], (val) => {
        init()
    })

    const { year, month, day } = toRefs(ymd)

</script>
学新通
<style lang="scss" scoped>
    #Calendar {
        $mainColor: rgba(255, 0, 0, 1);
        $mainLightColor: rgba(255, 0, 0, 0.1);
        $mainTextColor: #000000;
        $subtextColor: #C0C0C0;
        $btnTextColor1: #A9A9A9;
        $DefFFFFFF: #ffffff;
        [v-cloak] {
          display: none;
       }
        :deep(.van-overlay) {
            z-index: 2015;
            background: rgba(0, 0, 0, .5);
        }
        .calendar-view {
            width: 100%;
            height: 100%;
            display: flex;
        }
        .container {
            margin: auto;
            width: 343px;
            /* Background/Primary */
            background: $DefFFFFFF;
            border-radius: 12px;
            padding: 12px;
            box-sizing: border-box;
            .calendar-top-l {
                .ml10 {
                    margin-left: 10px;
                }
                .mr10 {
                    margin-right: 10px;
                }
                .calendar-top-left {
                    color: $mainColor;
                    font-size: 20px;
                }
                .calendar-top-right {
                    @extend .calendar-top-left;
                }
                .m {
                    line-height: 22px;
                    font-weight: 600;
                    font-size: 18px;
                }
                .y {
                    @extend .m;
                    margin-left: 10px;
                }
            }
            .calendar-top-r {
                @extend .calendar-top-l;
                .mr20 {
                    margin-right: 20px;
                }
            }
            .week {
                display: flex;
                align-items: center;
                margin-top: 16px;
                .week-op {
                    width: calc(100% / 7);
                    font-weight: 600;
                    font-size: 12px;
                    line-height: 16px;
                    color: #878787;
                    text-align: center;
                }
            }
            .date-g-v {
                margin-top: 12px;
            }
            .date-grid {
                display: flex;
                align-items: center;
                flex-wrap: wrap;
                width: 100%;
                height: 273.38px;
                .date-grid-list {
                    width: calc(100% / 7);
                    text-align: center;
                    position: relative;
                    padding-bottom: 14.285%;
                    border-radius: 100%;
                    overflow: hidden;
                    .date-view {
                        width: 100%;
                        position: absolute;
                        left: 0;
                        top: calc(50% - 11px);
                        font-weight: 400;
                        font-size: 18px;
                        line-height: 22px;
                        color: $mainTextColor;
                        .date-view-ab {
                            font-size: 10px;
                            color: $subtextColor;
                            position: absolute;
                            top: -3px;
                            right: 0;
                        }
                    }
                    .preDay {
                        color: $btnTextColor1 !important;
                    }
                    .nextDay {
                        @extend .preDay;
                    }
                    .date-day-current {
                        color: $mainColor !important;
                    }
                }
                .selBg {
                    background: $mainLightColor;
                }
            }
            .time {
                margin-top: 12px;
                .time-title {
                    font-weight: 600;
                    font-size: 18px;
                    line-height: 22px;
                    color: $mainTextColor;
                }
            }
            .w-time-picker {
                margin-top: 12px;
            }
            .time-confirm {
                @extend .w-time-picker;
            }
        }
        .display-flex {
            display: flex;
        }
        .align-items-center {
            align-items: center;
        }
        .justify-content-center {
            justify-content: center;
        }
        .justify-content-space-between {
            justify-content: space-between;
        }
        .justify-content-space-around {
            justify-content: space-around;
        }
        .justify-content-space-evenly {
            justify-content: space-evenly;
        }
        .flex-wrap {
            flex-wrap: wrap;
        }
        .flex-direction-row {
            flex-direction: row;
        }
        .flex-direction-row-reverse {
            flex-direction: row-reverse;
        }
        .flex-direction-column {
            flex-direction: column;
        }
        .flex-direction-column-reverse {
            flex-direction: column-reverse;
        }
    }
</style>
学新通
<template>
            <div v-if="calendarFlag">
                <!-- ymdhms 可以不传 -->
                <Calendar v-model:arise="calendarFlag"  :ymdhms="{ ymd: '2022/04/17', hms: '12:30:30' }"  @giveMe="handleGiveMe" />
            </div>
</template>
// 使用
<script setup>

   import { ref } from 'vue'
   import Calendar from '@/components/Calendar/index' // 组件路径

   const calendarFlag = ref(false)

    function handleGiveMe(e) {
        console.log(e)
    }

</script>
学新通

学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgfccbe
系列文章
更多 icon
同类精品
更多 icon
继续加载