使用APICloud AVM框架封装app日历组件

简介: AVM是APICloud推出的一个跨端的高性能 JavaScript框架,更趋近于原生的编程体验,它提供简洁的模型来分离应用的用户界面、业务逻辑和数据模型,适合高度定制化的项目。

实现的日历效果图


1.png


话不多说,上代码!


2.png


<template>
    <view class="page">
    <safe-area></safe-area>
    <view class="calendar-wrapper">
      <view class="calendar-toolbar">
        <text class="prev" onclick="prevMonth">〈</text>
        <text class="current">{{ currentDateStr }}</text>
        <text class="next" onclick="nextMonth">〉</text>
      </view>
      <view class="calendar-week">
        <text class="week-item" v-for="item of weekList" :key="item">{{ item }}</text>
      </view>
      <view class="calendar-inner">
        <text class="calendar-item" v-for="(item, index) of calendarList" :key="index" :class="this.changestyle(item.disable,item.value)"
        onclick="selDate" :data-val="item.value" :data-status="item.disable" :data-num="item.date">{{ item.date }}</text>
      </view>
    </view>
    </view>
</template>
<script>
  export default {
    name: 'calendar',
    installed(){
      this.setCurrent();
      this.calendarCreator();
    },
    data() {
      return{
        current:{}, 
        weekList:['周日','周一','周二','周三','周四','周五','周六'],
        shareDate: new Date(),
        calendarList: [],
        seldate:'点击选择日期',
        selweek:'待定',
      }
    },
    computed: {
      // 显示当前时间
      currentDateStr() {
        let { year, month } = this.current;
        return `${year}年${this.pad(month + 1)}月`;
      }
    },
    methods: {
      selDate (e){
        // console.log(JSON.stringify(e.currentTarget.dataset.val));
        let status = e.currentTarget.dataset.status;
        let num = e.currentTarget.dataset.num;
        if(status){
          this.data.seldate = e.currentTarget.dataset.val;
          this.getWeek();
          if(num>7){
            this.prevMonth();
          }
          else{
            this.nextMonth();
          }
        }
        else{
          this.data.seldate = e.currentTarget.dataset.val;
          this.getWeek();
          //重新加载一次日历 改变样式
          this.calendarCreator();
        }
        this.fire('clickDate', this.data.seldate);
      },
      changestyle(status,date){
        if(status){
          return 'calendar-item-disabled';
        }
        else{
          if(date == this.data.seldate){
            return 'calendar-item-checked';
          }
          else{
            return 'calendar-item';
          }
        }
      },
      // 判断当前月有多少天
      getDaysByMonth(year, month) {
        // console.log("本月多少天:"+new Date(year, month + 1, 0).getDate());
        return new Date(year, month + 1, 0).getDate();
      },
      getFirstDayByMonths(year, month) {
        // console.log("本月第一天周几:"+new Date(year, month, 1).getDay());
        return new Date(year, month, 1).getDay();
      },
      getLastDayByMonth(year, month) {
        // console.log("本月最后一天周几:"+new Date(year, month + 1, 0).getDay());
        return new Date(year, month + 1, 0).getDay();
      },
      // 对小于 10 的数字,前面补 0
      pad(str) {
        return str < 10 ? `0${str}` : str;
      },
      // 点击上一月
      prevMonth() {
        this.current.month--;
        // 因为 month的变化 会超出 0-11 的范围, 所以需要重新计算
        this.correctCurrent();
        // 生成新日期
        this.calendarCreator();
      },
      // 点击下一月
      nextMonth() {
        this.current.month++;
        // 因为 month的变化 会超出 0-11 的范围, 所以需要重新计算
        this.correctCurrent();
        // 生成新日期
        this.calendarCreator();
      },
      // 格式化时间,与主逻辑无关
      stringify(year, month, date) {
        let str = [year, this.pad(month + 1), this.pad(date)].join('-');
        return str;
      },
      // 设置或初始化 current
      setCurrent(d = new Date()) {
        let year = d.getFullYear();
        let month = d.getMonth();
        let date = d.getDate();
        this.current = {
            year,
            month,
            date
        }
      },
      // 修正 current
      correctCurrent() {
        let { year, month, date } = this.data.current;
        let maxDate = this.getDaysByMonth(year, month);
        // 预防其他月跳转到2月,2月最多只有29天,没有30-31
        date = Math.min(maxDate, date);
        let instance = new Date(year, month, date);
        this.setCurrent(instance);
      },
      // 生成日期
      calendarCreator() {
        // 一天有多少毫秒
        const oneDayMS = 24 * 60 * 60 * 1000;
        let list = [];
        let { year, month } = this.data.current;
        // 当前月份第一天是星期几, 0-6
        let firstDay = this.getFirstDayByMonths(year, month);
        // 填充多少天                         
        let prefixDaysLen = firstDay === 0 ? 7 : firstDay;
        // 毫秒数
        let begin = new Date(year, month, 1).getTime() - oneDayMS * prefixDaysLen;
        // 当前月份最后一天是星期几, 0-6
        let lastDay = this.getLastDayByMonth(year, month);
        // 填充多少天, 和星期的排放顺序有关
        let suffixDaysLen = lastDay === 0 ? 6 : 6 - lastDay;
        // 毫秒数
        let end = new Date(year, month + 1, 0).getTime() + oneDayMS * suffixDaysLen;
        while (begin <= end) {
            // 享元模式,避免重复 new Date
            this.data.shareDate.setTime(begin);
            let year = this.data.shareDate.getFullYear();
            let curMonth = this.data.shareDate.getMonth();
            let date = this.data.shareDate.getDate();
            list.push({
                year: year,
                month: curMonth,
                date: date,
                disable: curMonth !== month,
                value: this.stringify(year, curMonth, date)
            });
            begin += oneDayMS;
        }
        this.data.calendarList = list;      
        // console.log(JSON.stringify(this.data.calendarList));
      },
      //获取选中日期的周几
      getWeek(){
        let index =new Date(this.data.seldate).getDay();
        let weekArr = ['星期天', '星期一', '星期二', '星期三', '星期四', '星期五','星期六'];
        let week = weekArr[index];
        this.data.selweek = week;
      },
    }
  }
</script>
<style>
    .page {
        height: 100%;
    }
  .calendar-wrapper {
    margin: 10px 10px 0 10px;
    background-color:#3c40c6;
    border-top-left-radius: 10px;
    border-top-right-radius: 10px;
    max-height: 400px;
  }
  .calendar-toolbar {
    padding: 10px 10px;
    flex-flow: row nowrap;
    justify-content: space-between;
    align-items: center;    
    border-bottom: 1px solid #fff;
  }
  .prev{
    flex: 1;
    text-align: center;
    color: #fff;
  }
  .current {
    flex: 1;
    text-align: center;
    color: #fff;
  }
  .next{
    flex: 1;
    text-align: center;
    color: #fff;
  }
  .calendar-week {
    padding: 5px 10px;
    flex-flow: row nowrap;
    justify-content: space-around;
    align-items: center;
  }
  .week-item { 
    padding: 5px;
    font-weight: bolder;
    font-size: 12px;
    color: #fff;
  }
  .calendar-inner{
    padding: 10px 10px;
    flex-flow: row wrap;
    justify-content: space-around;
    align-items: center;
  }
  .calendar-item {
    width:14%;
    font-weight: bolder;
    text-align: center;
    font-size: 15px;
    color: #fff;
    padding: 5px;
    background-color: #3c40c6;
  }
  .calendar-item-disabled {
    width:14%;
    font-weight: bolder;
    text-align: center;
    font-size: 15px;
    color: #999;
  }
  .calendar-item-checked {
    width:14%;
    font-weight: bolder;
    text-align: center;
    font-size: 15px;
    color: #000000;
    background-color: #ffffff;
    border-radius: 5px;
  }
</style>

image.gif

其他页面引用

<template>
    <view class="page">
    <calendar onclickDate="getSelDate"></calendar>
    <view>
      <text>当前日期是</text>
      <text>{today}</text>
    </view>
    </view>
</template>
<script>
  import '../../components/calendar.stml'  
  export default {
    name: 'test',
    apiready(){
    },
    data() {
      return{
        today:''
      }
    },
    methods: {
      getSelDate(e){
        console.log(JSON.stringify(e));
        this.data.today = e.detail;
        api.toast({
          msg:'当前选中日期是:'+e.detail
        })
      }
    }
  }
</script>
<style>
    .page {
        height: 100%;
    }
</style>

image.gif

现在,APICloud 官方正在举办 AVM 组件的征集大赛,通过审核就能获得一定的奖金,大家感兴趣的也可以去围观一下。传送门:https://www.apicloud.com/activity2205

目录
相关文章
|
25天前
|
缓存 小程序 索引
uni-app开发微信小程序时vant组件van-tabs的使用陷阱及解决方案
uni-app开发微信小程序时vant组件van-tabs的使用陷阱及解决方案
133 1
|
26天前
|
存储 API 数据库
uniapp APP自动更新组件
uniapp APP自动更新组件
57 1
|
27天前
|
存储 前端开发 UED
uni-app:基础组件 (下)
本文介绍了多种前端组件及其用法,包括:label 组件用于表单元素的标签;picker 组件用于实现日期、时间及普通列表的选择器;textarea 组件用于输入多行文本,并可通过 v-model 双向绑定数据;process 组件用于显示进度条;swiper 组件用于轮播图展示;match-media 组件根据屏幕尺寸展示内容;audio 组件用于播放音频;switch 组件用于开关选择;scroll-view 组件实现滚动视图功能;以及 storage 的使用方法,如设置、获取和移除本地存储等。
|
27天前
|
存储 前端开发 JavaScript
uni-app:基础组件 (上)
本文介绍了uni-app中多个组件的使用方法,包括存储操作、图标展示、按钮样式、表单输入、导航跳转和输入框控制等。通过具体代码示例展示了如何设置存储键值、使用不同类型的按钮、实现表单提交与重置功能、控制输入框的显示与清除等功能。
|
2月前
|
移动开发 小程序 前端开发
uni-app组件样式修改不生效
uni-app组件样式修改不生效
|
2月前
|
开发框架 JavaScript 前端开发
uni-app x 跨平台开发框架
uni-app x 是一个强大的跨平台开发框架 uni-app x 是一个庞大的工程,它包括uts语言、uvue渲染引擎、uni的组件和API、以及扩展机制。
82 1
|
3月前
|
存储 BI Android开发
全开源仿第八区H5APP封装打包分发系统源码
全开源仿第八区H5APP封装打包分发系统源码
135 4
|
3月前
|
XML 数据格式
【Azure Logic App】在Logic App中使用 Transfer XML组件遇见错误 undefined
【Azure Logic App】在Logic App中使用 Transfer XML组件遇见错误 undefined
|
3月前
|
Python Windows 内存技术
【Azure 应用服务】Azure App Service (Windows) 使用Flask框架部署Python应用,如何在代码中访问静态文件呢?如何设置文件路径?是相对路径还是绝对路径呢?
【Azure 应用服务】Azure App Service (Windows) 使用Flask框架部署Python应用,如何在代码中访问静态文件呢?如何设置文件路径?是相对路径还是绝对路径呢?
|
4月前
|
存储 前端开发
useEffect问题之在子组件的副作用中更新父组件的状态如何解决
useEffect问题之在子组件的副作用中更新父组件的状态如何解决