时间日期五级联动组件封装和demo——微信小程序组件


微信自带的组件只有时间和日期,分开的的组件,所以自己封装了一个时间日期联动的组件

一、组件需求

  1. 可以传入初始时间,否则就是当前时间
  2. 可以选择日期时间
  3. 可以做一些限制,比如选择年份的范围,是否可以选择当前日期之后的日期
    在这里插入图片描述

二、实现思路

2.1使用小程序组件进行组装

在这里插入图片描述
结构如下
在这里插入图片描述

2.2 难点

个人觉得时间日期的唯一一个坑点是,2月份的瑞年天数变动,实现的方案是,以前在android踩过很多坑,直接把所有数据都直接引入,这样很不便捷,幸好,小程序已经封装好了很多功能,比如滑动监听,让简单化的实现成为可能:
解决方案如下:
在动态的获取中,监听年份和月份的变化,只有当年份和月份发生变化时,才触发更新天数,其中除了2月份,其他的天数均直接写四,代码如下:

_getMonthDays(year,month) {
     let that = this;
     // 优化算法,只有当月份是2月份的时候,才会动态加载
     if ([1, 3, 5, 7, 8, 10, 12].includes(month)) {
       return 31;
     } else if ([4, 6, 9, 11].includes(month)) {
       return 30;
     } else {
       return new Date(year, month,0).getDate(); // 这个技巧是,获取上月最后一天是上月的第多少天,比如,我们想获取2月份的天数,就传入3月份的第零0天,因为天数是从1开始,那么0就是2月份的最后以一天
     }
   },

提示一下,月份是从0开始的哦

三、实现

3.1 布局文件

为了实用和美观,我们不仅要实现功能,还要有背景遮罩,定位的底部,先上布局文件.wxml

<view class='mask' hidden="{{!showDatePick}}">
  <view class='content'>
    <view class='header'>
      <view class='cancle' bindtap='_cancle'>取消</view>
      <view class='confirm' bindtap='_confirm'>确定</view>
    </view>
    <picker-view
      indicator-class='select'
      class='pick-view'
      value="{{currentDate}}"
      bindchange="_bindChange">
      <picker-view-column>
        <view class="item" wx:for="{{yearList}}" wx:key="{{index}}">{{item}}年</view>
      </picker-view-column>
      <picker-view-column>
        <view class="item" wx:for="{{monthList}}" wx:key="{{index}}">{{item}}月</view>
      </picker-view-column>
      <picker-view-column>
        <view class="item" wx:for="{{dateList}}" wx:key="{{index}}">{{item}}日</view>
      </picker-view-column>
      <picker-view-column>
        <view class="item" wx:for="{{hourList}}" wx:key="{{index}}">{{item}}时</view>
      </picker-view-column>
      <picker-view-column>
        <view class="item" wx:for="{{minusList}}" wx:key="{{index}}">{{item}}分</view>
      </picker-view-column>
    </picker-view>
  </view>
</view>

应该能看懂,具体的wxss文件可以到github下载查看,最后会贴上demo

3.2 js核心代码
// components/aydk_date_ymdhm/aydk_date_ymdhm.js
const MAX_REGION_YEAR = 50;// 默认年的区间是当前时间的开始和结束50年
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    // isAfter:{ // 是否允许选择当前日期之后的日期 之后优化再做,谁有兴趣可以优化一下
    //   type:Boolean,
    //   value: false
    // },
    initDate:{ //初始化时间,格式是string,可以被new Date(param) 初始化的时间
      type:String,
      value: new Date().getTime()
    },
    showDatePick:{
      type: Boolean,
      value: false,
      observer: function (newVal, oldVal) {
        // 属性值变化时执行
        let that = this;
        if(newVal){
          that._initCurrentDate();
        }
      }
    }
  },

  /**
   * 组件的初始数据
   */
  data: {
    showDatePick: false,
    currentDate: [0,0,0,0,0],
    yearList: [],
    monthList: [],
    dateList: [],
    hourList: [], //代码初始化
    minusList: [] // 代码初始化
  },
  //初始化写到挂载事件中,不能写到create钩子里
  attached() {
    let that = this;
    that._initCurrentDate();
    that._initHour();
    that._initMinus();
  },
  // 为了保证数据初始化完成
  ready() {
    let that = this;
    that.setData({
      currentDate: that.data.currentDate
    })
  },
  /**
   * 组件的方法列表
   */
  methods: {
    /**
     * 函数调用,可选
     * @date 初始化时间,可选
     */
    showDate(date){
      let that = this;
      if(date) {
        this.initDate = date;
      }
      that._initCurrentDate();
      that.setData({
        showDatePick: true
      })
    },
    /**
     * 初始化开始时间
     */
    _initCurrentDate() {
      let that = this;
      let now = new Date(that.data.initDate);
      that.data.currentDate[1] = now.getMonth(); // 初始化月份
      that.data.currentDate[2] = now.getDate()-1; // 初始化天
      that.data.currentDate[3] = now.getHours(); // 初始化小时
      that.data.currentDate[4] = now.getMinutes(); // 初始化分钟
      that._initYear(now.getFullYear()); // 初始化年
      that._initMonth(); // 初始化月份
      that._initDate(now.getFullYear(), now.getMonth()+1); // 初始化天
    },
    /**
     * 初始化年滚动
     * 参数为当前年
     */
    _initYear(year) {
      let that = this;
      that.data.yearList = [];
      for (let orgion = 0; orgion < MAX_REGION_YEAR; orgion++){
        if(year-orgion>=1970){
          that.data.yearList.unshift(year-orgion);
        }
        that.data.yearList.push(orgion+year+1);// 当前年份已经push了
      }
      that.data.currentDate[0] = that.data.yearList.indexOf(year);
      that.setData({
        currentDate: that.data.currentDate,
        yearList: that.data.yearList
      })
    },
    _initMonth(){
      let that = this;
      that.setData({
        monthList:Array.from(Array(12), (v,k)=>(k+1))
      })
    },
    _initDate(year,month) {
      let that = this;
      that.setData({
        dateList: Array.from(Array(that._getMonthDays(year,month)), (v, k) => (k + 1))
      })
    },
    _initHour() {
      let that = this;
      that.setData({
        hourList: Array.from(Array(24), (v, k) => k)
      })
    },
    _initMinus() {
      let that = this;
      that.setData({
        minusList: Array.from(Array(60), (v, k) => k)
      })
    },
    _getMonthDays(year,month) {
      let that = this;
      // 优化算法,只有当月份是2月份的时候,才会动态加载
      if ([1, 3, 5, 7, 8, 10, 12].includes(month)) {
        return 31;
      } else if ([4, 6, 9, 11].includes(month)) {
        return 30;
      } else {
        return new Date(year, month,0).getDate();
      }
    },
    _bindChange(e){
      let that = this;
      if (e.detail.value[0] !== that.data.currentDate[0] || e.detail.value[1] !== that.data.currentDate[1]) {
        that._initDate(that.data.yearList[e.detail.value[0]], that.data.monthList[e.detail.value[1]]);
      }
      that.data.currentDate = e.detail.value;
    },
    _cancle(){
      let that = this;
      that.setData({
        showDatePick: false
      })
    },
    _confirm(){
      let that = this;
      that.setData({
        showDatePick: false
      })
      that.triggerEvent('getDate', [that.data.yearList[that.data.currentDate[0]], that.data.monthList[that.data.currentDate[1]],that.data.dateList[that.data.currentDate[2]],that.data.hourList[that.data.currentDate[3]],that.data.minusList[that.data.currentDate[4]]]);
    }
  }
})

3.3 最后上调用代码
	//先在json中声明
	"usingComponents": {
    	"date":"../../components/aydk_date_ymdhm/aydk_date_ymdhm"
  	}
	// 使用代码 ,这只是最基本的调用
	<date 
	  showDatePick='{{showDatePick}}'
	  bind:getDate="getDateData">
	</date>
  

四、问题(留给你们)

写的时候为求速度,到快写完发现准备加上点击遮罩关闭组件,但是发现布局设计的不太合理,没办法加,还有就是最后的返回数据,应该可以返回数组和时间,让调用更傻瓜点。
好啦,基本结束啦

五、demo

组件demo

欢迎加群交流哦
在这里插入图片描述

发布了60 篇原创文章 · 获赞 66 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/u012436704/article/details/90552678
今日推荐