vue自定义日历小组件

这篇具有很好参考价值的文章主要介绍了vue自定义日历小组件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

vue自定义小日历组件

一、前言

自己开发的项目需要用到类似博客侧边栏小日历组件,觉得自己造一个比较随心所欲,更能满足自己的需求,所以决定自己开发一个。最终效果如图所示。
vue自定义日历小组件

二、日历样式

我的这个日历组件主要分为导航栏区和主要内容区,导航栏按钮样式什么的都是自定义的,很简单,源码有就不罗嗦。主要讲一下日历内容的样式设计。

vue自定义日历小组件

日历内容都是用<ul><li>标签实现的,星期栏和日期栏分别为独立的<ul>,内容为<li>,两个<ul>均采用网格布局,星期栏1行7列,日期内容为6行7列,在css样式中设置display为grid,再分别设置行列属性,<li>会自动排布为设定的样式,这里前提是每个<li>要设置为inline-block排布。

vue自定义日历小组件

关于grid布局可以参考这篇文章:CSS Grid 网格布局教程 - 阮一峰的网络日志 (ruanyifeng.com) 这篇博客讲得非常好。

template示例(完整版见末尾链接下载):

<div id="app">
        <div class="calendar-card">
            <div class="calendar-bar">
                <button class="button button-year-minus">&lt;</button>
                <button class="button button-month-minus">&lt;</button>
                <div class="calendar-date">{{date.year}}-{{date.month}}-{{date.date}}</div>
                <button class="button button-month-plus">&gt;</button>
                <button class="button button-year-plus">&gt;</button>
            </div>
            <div class="calendar-content">
                <ul class="ul-week">
                    <li class="li-week" v-for="item in week">{{item}}</li>
                </ul>
                <ul class="ul-day">
                    <li class="li-day" v-for="item in days">{{item}}</li>
                </ul>
            </div>
        </div>
    </div>

js代码:

var vm = new Vue({
            el:"#app",
            data:{
                date:{
                    year:2022,
                    month:5,
                    date:11
                },
                week:["日","一","二","三","四","五","六"],
                days:[]//用来绑定日期的数组
            }created(){
                for(let i=0;i<42;i++){   //生成日期数组(示范)
                    this.days.push(i)
                }
            }
        })

css样式:

.ul-week {
    display: grid;
    width: 245px;
    grid-template-rows: 20px;/*一个值只有一行20px高*/
    grid-template-columns: repeat(7, 35px);/*重复7个值代表7列35px宽*/
    
    list-style: none;/*记得清除ul的li标签的·样式*/
    text-align: center;
    
    font-size: 13px;
    color: #aaa;
    
    margin: 5px 20px 5px 20px;
    padding-inline-start: 0px;/*清除ul多余样式*/
    padding-inline-end: 0px;/*清除ul多余样式*/
    border-bottom: 1px solid #eee;/*分隔线*/
}

.li-week {
    display: inline-block;/*li标签设为行内排列*/
}
/*日期内容样式注释参照上面的自己理解*/
.ul-day {
    display: grid;
    width: 245px;
    grid-template-rows: repeat(6, 22px);/*6行22px高*/
    grid-template-columns: repeat(7, 35px);/*7列35px宽*/
    
    list-style: none;
    text-align: center;
    
    margin: 5px 20px 5px 20px;
    padding-inline-start: 0px;
    padding-inline-end: 0px;
}

.li-day {
    display: inline-block;/*必须设置为行内排布,否则为列排布,日期是竖着显示,虽然再grid布局下看上去一样*/
    font-size: 10px;
    line-height: 22px;
    text-align: center;
    border-radius: 5px;
    margin: 1px;
}

三、日历实现

1.实现显示当月日历

创建两个data的对象:datecurrentdate用来存放需要切换的日期,current用来存放今天的年月日

date: {
    year: "",
    month: "",
    date: ""
},
current: {
    year: "",
    month: "",
    date: "",
}

我们前面用days:[]绑定了日期的<li>,总共有6x7=42<li>,所以每月只要生成对应的包含42个日期元素的days数组,就能够自动更新日历。先不考虑按钮切换年月,先实现本月日历的生成。我们前面讨论的其本质就是生成当月的42元素数组days,下面给出的就是实现的代码,注释会介绍:

/**
 * 根据参数year和month生成对应年月的日历数组
 */
createCalendar: function (year, month) {
    let d = new Date();         //获得date对象
    d.setFullYear(year);        //设置date为制定年份
    d.setMonth(month);          //设置date为制定月份(0~11)
    d.setDate(1);               //设置为本月第一天,为了是下面计算第一天是星期几
    let dayOfFirstDay = d.getDay();    //获得对应月份第一天是星期几(0~6)
    this.days = []                     //每次生成日历清空日期数组

    //向days数组填充每一个日期,包括上个与的末尾和下个月的开头总共42个日期
    /**
    *如何获得上个月末尾和下个月开头?
    *date对象可以设置年月日,其中设置每月几号为setDate(day) day一般为(1~31)
    *当day为0时,date设置的日期是上个月最后一天
    *当day为-1时,date设置的日期是上个月的倒数第二天,以此类推
    *当day设置超过当月天数时,比如三月的32,则会被设置为四月第一天
    *所以循环42次,每次设置对应的day,就可以生成完整日期数组,包括上月尾巴和下月的开头
    */
    for (let i = 0; i < 42; i++) {
        //每次循环重新设置为每月开头第一天,否则每次循环像本月只有28天,上轮循环到31,切换月份到本月的时候31超过28,date对象的month会被设置为下个月
        d.setDate(1);                      
        //每次循环重新设置月份,因为setDate()为负数或这超过本月天数,date对象的month会被设置成上个月或下个月,然后在下一轮循环就会出错
        d.setMonth(month)                     
        d.setDate(i - dayOfFirstDay + 1) //设置本轮循环对应的day,dayOfFirstDay为本月第一天的星期,本月第一天之前的day小于1,也就是0或者负数,需要减去dayOfFirstDay差+1,这里自己体会
        if (this.current.date == d.getDate() && this.current.month == d.getMonth() && this.current.year == d.getFullYear()) { //此为判断本次循环是否为当天,当天日期可以做标记以高亮显示,如加上“*”号
            this.days.push(d.getDate()+"*")  //往数组里push本次循环的日期
        } else {
            this.days.push(d.getDate())     //往数组里push本次循环的日期
        }
    }

}

为了在生成日历组件的同时初始化日历,所以需要在create()中做初始化处理

created() {
    let d = new Date();
    //初始化标题显示的年月日
    this.date.year = d.getFullYear(); 
    this.date.month = d.getMonth();
    this.date.date = d.getDate();
    
    //初始化今天的年月日
    this.current.year = d.getFullYear();
    this.current.month = d.getMonth();
    this.current.date = d.getDate();
    
    //调用createCalendar()生成本月的日历
    this.createCalendar(this.current.year,this.current.month)
}

最后的效果如下:

vue自定义日历小组件

2. 区分本月和其他月

上月末尾日期和下月开头日期与本月日期混在一起,需要做一些样式处理。我们将days数组从原先的存放day数字,改为存放date对象,{year:"2022",month:"5",date:"11",isThisMonth:false},存放年月日,其中isThisMonth

为该日期是否是本月的标记,”1“为非本月,”2“为本月。然后通过css选择器属性来实现。

createCalendar()中改成如下代码:

createCalendar: function (year, month) {
    let d = new Date();
    d.setFullYear(year);
    d.setMonth(month);
    d.setDate(1);
    let dayOfFirstDay = d.getDay();
    this.days = []
    
    for (let i = 0; i < 42; i++) {
        d.setDate(1);
        d.setMonth(month)
        d.setDate(i - dayOfFirstDay + 1)

        //判断是否为本月并添加标记
        let isThisMonth = 2
        if (d.getMonth() == month) {
            isThisMonth = 2
        } else {
            isThisMonth = 1
        }

        
        if (this.current.date == d.getDate() && this.current.month == d.getMonth() && this.current.year == d.getFullYear()) {
            isThisMonth = 3
            //改为对象
            let date = { year: year, month: month, date: d.getDate(), isThisMonth: isThisMonth }
            this.days.push(date)
        } else {
            //改为对象
            let date = { year: d.getFullYear(), month: d.getMonth(), date: d.getDate(), isThisMonth: isThisMonth }
            this.days.push(date)
        }

css运用选择器属性:

.li-day[isThisMonth="1"] {       /*非本月的本月样式*/
    color: rgb(190, 190, 190);
    font-size: 10px;
}

.li-day[isThisMonth="1"]:hover {/*非本月的本月样式hover*/
    background-color: #717de2;
    color: #fff;
    font-size: 15px;
    cursor: pointer;
}

对应标签改为:

<ul class="ul-day">
    <li class="li-day" v-for="item in days" :isThisMonth="item.isThisMonth">{{item.date}}</li>
</ul>

即可以实现如下的效果:

vue自定义日历小组件

3.高亮今天的日期

我们在2的基础上,在isThisMonth判断上再加一个值3,如果当前day是今天,则标记为”3“。在createCalendar()判断是否为今天的代码修改为如下(可以把丑陋的"*"去掉了):

 if (this.current.date == d.getDate() && this.current.month == d.getMonth() && this.current.year == d.getFullYear()) {
     //标志为3代表是今天
     isThisMonth=3
     let date = { year: year, month: month, date: d.getDate(), isThisMonth: isThisMonth }
     this.days.push(date)
 }

css样式里添加如下代码:

.li-day[isThisMonth="3"] {
    border-radius: 5px;
    color: rgb(255, 255, 255);
    background-color: #79bbff;
    font-weight: 600;
  }

则实现了今天的日期高亮的效果:

vue自定义日历小组件

4.实现切换年月从而切换日历

给button绑定事件,本质就是修改data中的date.yeardate.month,并且每次修改年月都要调用createCalendar()重新更新日历。代码如下,其中的逻辑很简单,看下代码就懂的:

plusMonth: function () {
    if (this.date.month == 11) {
        this.date.month = 0;
        this.plusYear(false) //切换月份超过当年范围会导致年份增减,但是直接调用增减年份的函数会导致日历重复更新,所以在增减年份的函数中添加标志位,flase则不更新日历
    } else {
        this.date.month++;
    }
    this.createCalendar(this.date.year, this.date.month);
},
minusMonth: function () {
    if (this.date.month == 0) {
        this.date.month = 11;
        this.minusYear(false)   //切换月份超过当年范围会导致年份增减
    } else {
        this.date.month--; 
    }
    this.createCalendar(this.date.year, this.date.month);
},
plusYear: function (create) {          //freate为flase则不更新日历
    if (this.date.year == 2049) {
        this.date.year = 1970;
    } else {
        this.date.year++;
    }
    if (create) {
        this.createCalendar(this.date.year, this.date.month);
    }
},
minusYear: function (create) {
    if (this.date.year == 1970) {
        this.date.year = 2049;
    } else {
        this.date.year--;
    }
    if (create) {
        this.createCalendar(this.date.year, this.date.month);
    }
}

给每个按钮绑定

<button class="button button-year-minus" @click="minusYear">&lt;</button>
<button class="button button-month-minus" @click="minusMonth">&lt;</button>
<div class="calendar-date">{{date.year}}-{{date.month+1}}-{{date.date}}</div>
<button class="button button-month-plus" @click="plusMonth">&gt;</button>
<button class="button button-year-plus" @click="plusYear">&gt;</button>

四、高级功能

给每个日期<li>点击事件@click,绑定handleClick()方法

<ul class="ul-day">
    <li class="li-day" v-for="item in days" :isThisMonth="item.isThisMonth" @click="handleClick(item)">{{item.date}}</li>
</ul>

添加handleClick()方法:

 handleClick: function (item) {
     console.log(item.year + "-" + item.month + "-" + item.date)
     alert(item.year + "-" + item.month + "-" + item.date)
 }

后续可以在handleClick()方法中定制自己的处理,例如点击某天实现某些页面的路由等等,可以将改天的年月日作为参数进行请求,实现DatePicker功能。

五、源码下载

所有源码可以在github https://github.com/PengQitao/gram-simple-calendar.git中下载,如果喜欢记得给个⭐star哦文章来源地址https://www.toymoban.com/news/detail-403906.html

到了这里,关于vue自定义日历小组件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • uniapp----微信小程序 日历组件(周日历&& 月日历)【Vue3+ts+uView】

    用Vue3+ts+uView来编写日历组件; 存在周日历和月日历两种显示方式; 高亮显示当天日期,红点渲染有数据的日期,点击显示数据 1. calendar-week-mouth组件代码 2. 在页面引用组件

    2024年02月04日
    浏览(73)
  • 《Vue3+Typescript》一个简单的日历组件实现

    这是一个没有套路的前端博主,热衷各种前端向的骚操作,经常想到哪就写到哪,如果有感兴趣的技术和前端效果可以留言~博主看到后会去代替大家踩坑的~ 主页: oliver尹的主页 格言: 跌倒了爬起来就好~ 目录 一、前言 二、效果图 三、核心思路 四、代码实现 4.1 本月日期

    2024年02月14日
    浏览(42)
  • Vue中的日历组件 Calendar 实现 考勤打卡记录

    实现效果图 1.由于Calendar没有右上角月份切换的API事件,可以给组件源码添加自定义添加一个事件 2.也可以通过自带的input事件来获取日历 3.vue页面完整代码 注释:this.$m(this.beginTime).format(‘YYYY-MM-DD HH:mm’),是分装的标准时间转化年月日,使用者可通过多种方法自定义处理。

    2024年01月22日
    浏览(60)
  • vue平铺日历组件之按住ctrl、shift键实现跨月、跨年多选日期的功能

    已经好久没有更新过博客了,大概有两三年了吧,因为换了工作,工作也比较忙,所以也就没有时间来写技术博客,期间也一直想写,但自己又比较懒,就给耽误了。今天这篇先续上,下一篇什么时候写,我也不知道,随心所欲、随遇而安、安之若素、素不相识也就无所谓了

    2024年02月06日
    浏览(53)
  • 【分页表格】Vue2 + Element UI实现自定义的分页表格组件(自定义Vue组件)

    这篇文章,主要介绍Vue2 + Element UI实现自定义的分页表格组件(自定义Vue组件)。 目录 一、分页表格 1.1、运行效果 1.2、运行环境 1.3、案例代码

    2024年02月11日
    浏览(59)
  • Vue组件解析:自定义表格组件ByTable详解

    【简介】:本文将介绍一个基于Vue框架和elementUi的自定义表格组件ByTable,通过阅读本文,你将了解到ByTable组件的使用方式、属性和插槽的配置方法,以及如何通过自动请求接口获取表格数据和实现分页功能。 ByTable是一个通用的Vue表格组件,用于展示数据并提供分页功能。它

    2024年02月10日
    浏览(40)
  • uniapp 简易自定义日历

    注:此日历是根据接口返回的日期自动对应星期的,返回的数据中也包含星期,其实就是一个div自定义,可根据自己需求更改; 1、组件代码 gy-calendar-self.vue 2、引入 最后附上返回的数据格式: 只需要 dateWork 和 week

    2024年01月18日
    浏览(41)
  • 31 3D日历组件

    实现了一个3D文字旋转的效果,当鼠标悬停在容器上时,最后一个文字会旋转630度,而其他文字会逐渐旋转到水平面上方。 这段代码是设置全局样式,将所有元素的外边距、内边距和盒模型设置为0,以便更好地控制元素的大小和位置。 这段代码是设置页面的基本样式,将页

    2024年01月18日
    浏览(37)
  • flutter 手写日历组件

    先看效果  直接上代码 calendar_popup_view.dart custom_calendar.dart hotel_app_theme.dart RangePicker.dart  这个文件是使用的地方 这里还使用到了  getx 的组件 从底部弹出

    2024年02月13日
    浏览(38)
  • vue3笔记:自定义组件

    自定义组件,举个🌰: 1、封装自定义组件 CustomList.vue src 底下 type 文件夹中声明的 interface 接口文件 2、在 App.vue 中使用自定义组件 CustomList.vue 1、全局注册 在 main.ts 中使用 app.component(\\\'MyComponent\\\', MyComponent) 全局注册一个组件,可以在app内的任何地方使用。 缺点: 无法在生产打

    2024年02月08日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包