高仿‘携程’移动端日历选择组件

738 阅读2分钟

最近需求是关于小程序开发的,有个开始时间和截止时间的选择,产品拿着携程的小程序,轻飘飘一句:就要这样的!

好吧!咱也试试嘛!

一顿操作猛如虎,先百度,后google!找半天纯浪费时间,认清了自己也有脑子的事实!

对着下图开始瑜伽冥想


后来有了它!

略微简单了点,但也是五脏俱全了,第一次记录,分享!不足之处请指正。

export default class DateSelection extends Component {  currentDateTimer = null;  historyDateTimer = null;  daysArr = [];  weekArr = ['一', '二', '三', '四', '五', '六', '日'];  startDate = null;  endDate = null;  @observable updateCounter = 0;  componentWillMount() {    const {startDate, endDate} = this.$router.params;    this.init();    if (startDate && endDate) {      if (this.dateToTime(endDate) >= this.dateToTime(startDate)) {        this.startDate = startDate;        this.endDate = endDate;      } else {        this.startDate = endDate;        this.endDate = startDate;      }    }    this.updateCounter++;  }  componentDidMount() {    Taro.pageScrollTo({      scrollTop: 1660,      duration: 900    })  }  init() {    let hisDays = 180;    //当前时间    let currDate = new Date();    this.currentDateTimer = currDate.getTime();    let currYear = currDate.getFullYear();    let currMonth = currDate.getMonth() + 1;    //n天前所在月份    let hisDate = new Date(currDate.getTime() - hisDays * 24 * 3600 * 1000);    this.historyDateTimer = hisDate.getTime();    let hisYear = hisDate.getFullYear();    let hisMonth = hisDate.getMonth() + 1;    if (currYear === hisYear) {      this.daysArr = this.handleDateArr(hisMonth, currMonth, currYear);    } else {//跨年      this.daysArr.push(this.handleDateArr(hisMonth, 12, hisYear));      this.daysArr.push(this.handleDateArr(1, currMonth, currYear));    }  }  handleDateArr(startMonth, endMonth, currentYear) {    let daysArr = [];    for (let i = startMonth; i <= endMonth; i++) {      //本月第一天是星期几      let firstDayIndex = new Date(currentYear, i - 1, 1).getDay();      //转换星期一为每周第一天      firstDayIndex = firstDayIndex === 0 ? 7 : firstDayIndex;      //本月最后一天(当月一共有多少天)      let lastDay = new Date(currentYear, i, 0).getDate();      let tempDate = [];//存储当月每一天      for (let j = 1; j < firstDayIndex; j++) {        tempDate.push(0);//占位      }      for (let j = 1; j <= lastDay; j++) {        tempDate.push(`${currentYear}/${i}/${j}`);      }      let tempMonthDate = {yearMonth: `${currentYear}/${i}`, days: tempDate};      daysArr.push(tempMonthDate);    }    return daysArr;  }  dateToTime(date) {    return new Date(date).getTime();  }  changeDate = (day) => {    let startDate = this.startDate;    let endDate = this.endDate;    let startTimer = this.dateToTime(startDate);    let dayTimer = this.dateToTime(day);    //两个都有默认值    if (startDate && endDate) {      startDate = day;      endDate = null;    } else {      //都没有值      if (!startDate) {//startDate没有值        startDate = day;        endDate = null;      } else {//startDate有值        if (dayTimer < startTimer) {          startDate = day;          endDate = null;        } else {//dayTime>=startTimer          if (dayTimer === startTimer) {            startDate = day;            endDate = day;          } else {            endDate = day;          }        }      }    }    this.startDate = startDate;    this.endDate = endDate;    if (startDate && endDate) {      globalStore.changeTeacherIndexDateRange(startDate, endDate);      Taro.navigateBack({        delta: 2      })    }    this.updateCounter++;  }  render() {    let updateCounter = this.updateCounter;    let weekArr = this.weekArr;    let daysArr = this.daysArr;    let currentDateTimer = this.currentDateTimer;    let historyDateTimer = this.historyDateTimer;    let startDate = this.startDate;    let endDate = this.endDate;    return (      <View>        <View className='weekArrBox'>          {            weekArr.map((week, i) => {              return (                <View key={`weekArr${i}`} className='weekArr'>{week}</View>              )            })          }        </View>        <View>          {            daysArr.length > 0 && daysArr.map((month, index) => {              let title = month.yearMonth.split('/');              return (                <View key={`daysArr${index}`}>                  <Text className='title'>{`${title[0]}${title[1]}月`}</Text>                  <View className='monthBox' key={`monthBox${index}`}>                    {                      month.days.map((day) => {                        let dayTimer = new Date(day).getTime();                        let isDisabled = dayTimer > currentDateTimer || dayTimer < historyDateTimer;                        let isStart = (day === startDate);                        let isEnd = (day === endDate);                        let dateOfDay = !day ? '' : day.split('/')[2];                        let dayFlag = '';                        if (isEnd && isStart) {                          dayFlag = '';//相同                        } else {                          if (isStart) {                            dayFlag = '开始';//开始                          }                          if (isEnd) {                            dayFlag = '结束';//结束                          }                        }                        return !isDisabled ?                          <View key={`day${day}`}                                className={`item ${isStart ? 'activeStart' : ''} ${isEnd ? 'activeEnd' : ''}`}                                onClick={this.changeDate.bind(this, day)}>{dateOfDay}                            {                              <View className='flag'>{dayFlag}</View>                            }                          </View>                          : <View key={`day${day}`} className='item disabled'>{dateOfDay}</View>                      })                    }                  </View>                </View>              )            })          }        </View>      </View>    )  }}

page{  background: #fff;  border-bottom: 10px solid #fff;}.weekArrBox {  height: 80px;  position: sticky;  display: flex;  flex-wrap: wrap;  align-items: center;  top: 0;  margin: 0 auto;  background: #f5f5f5;  font-size: 28px;  z-index: 1;}.weekArr {  width: 14.28%;  text-align: center;}.title{  display: block;  text-align: center;  font-size: 32px;  height: 100px;  line-height: 100px;}.monthBox {  display: flex;  flex-wrap: wrap;  align-items: flex-start;  font-size: 28px;  .item {    position: relative;    width: 14.28%;    margin-top: 10px;    padding: 30px 0;    text-align: center;  }  .disabled{    color: #cfcfcf;  }  .active{    color: #fff;    background: #0e8aed;  }  .activeStart{    .active;  }  .activeEnd{    .active;  }  .flag{    position: absolute;    left: 0;    right: 0;    bottom: 4px;    font-size: 24px;  }}