原生JS实现日期三级联动与范围选择

作者:异步漫步时间:2026-10-28 19:42:34浏览:315

本文介绍如何使用原生JavaScript实现年月日三级联动下拉框,并支持指定日期范围选择。通过switch语句优化月份天数判定,处理闰年逻辑,确保日期选择的准确性与性能。

月份判定与性能优化

在判断月份天数时,若使用大量的if-else条件判断会显著降低代码性能。因此,建议采用switch语法来处理不同月份的天数判定,以提高执行效率。

具体实现代码如下:

核心逻辑代码:

getDays:function(year,month){
// var aDay = [31,28|29,31,30,31,30,31,31,30,31,30,31];
// 二月份的天数数据处理
var FedDays = year%4==0?29:28,
returnDays = '';
var month = month<10?month = '0'+month:month.toString();
switch(month){
case '01':
case '03':
case '05':
case '07':
case '08':
case '10':
case '12': returnDays = 31;break;
case '04':
case '06':
case '09':
case '11': returnDays = 30;break;
case '02': returnDays = FedDays;break;
        }
return returnDays;
    }

完整日期联动实现代码

完整源代码如下:

完整实现代码:

/* author:laoguoyong
------------------------------
日期三级联动,范围选择
------------------------------
参数
* [String] targets:'#year,#month,#day' ;年,月,日的id
* [String] range:'2013-02-03,2019-09-21';范围,正确格式为xxxx-xx-xx
----为了节省代码,请传入正确的日期范围参数
----错误示范:
(1)range:'2013-02-03,2019-9-21' 是不对的,注意日期格式
(2)range:'2013-02-03' 是不对的,请输入完整的范围之值
(3)range:'2013-02-03,2016-02-30' 是不对的,2月没有30天
(3)range:'2013-02-03,2011-02-30' 是不对的,范围错误了
*
*/
function GySetDate(opt){
//elem
var targets = opt.targets.split(',');
this.eYear = this.getId(targets[0].slice(1));
this.eMonth = this.getId(targets[1].slice(1));
this.eDay = this.getId(targets[2].slice(1));
if(!this.eYear||!this.eMonth||!this.eDay) return;
//范围值
var r = opt.range.indexOf(',')
aStarts = opt.range.slice(0,r).split('-'), // 转为:['2013','05','20']
aEnds = opt.range.slice(r+1,opt.range.length).split('-'); // 转为:['2018','08','20']
//Number类型
this.startYear = parseInt(aStarts[0],10);
this.startMonth = parseInt(aStarts[1],10);
this.startDay = parseInt(aStarts[2],10);
this.endYear = parseInt(aEnds[0],10);
this.endMonth = parseInt(aEnds[1],10);
this.endDay = parseInt(aEnds[2],10);
this.init();
}
GySetDate.prototype = {
 init:function(){
 var _that = this;
 // 初始化日期
 this.setYears({'start':this.startYear,'end':this.endYear});
 this.setMonths({'start':this.startMonth});
 this.setDays({'year':this.startYear,'month':this.startMonth,'start':this.startDay});
 // 年选择
 this.eYear.onchange = function(){
 var year = parseInt(this.value);
 switch(true){
 case (year == _that.startYear):{
 _that.setMonths({'start':_that.startMonth});
 _that.setDays({'year':_that.startYear,'month':_that.startMonth,'start':_that.startDay});
 };break;
 case (year == _that.endYear):{
 _that.setMonths({'start':1,'end':_that.endMonth});
 if(_that.endMonth>1){
 _that.setDays({'year':_that.endYear,'month':1,'start':1}); 
 }else{
 _that.setDays({'year':_that.endYear,'month':1,'start':1,'end':_that.endDay});
 }
 };break;
 default:{
 _that.setMonths({'start':1});
 _that.setDays({'start':1,'year':year,'month':1});
 }
 }
 
 }
 // 月选择
 this.eMonth.onchange = function(){
 var year = parseInt(_that.eYear.options[_that.eYear.selectedIndex].value),
 month = parseInt(this.value);
 switch(true){
 case (year==_that.endYear&&month==_that.endMonth):{
 _that.setDays({'start':1,'year':year,'month':month,'end':_that.endDay});
 };break;
 case (year==_that.startYear&&month==_that.startMonth):{
 _that.setDays({'year':_that.startYear,'month':_that.startMonth,'start':_that.startDay});
 };break;
 default:{
 _that.setDays({'start':1,'year':year,'month':month});
 }
 } 
 
 }
 },
 /*设置年,月,日
 ----------------------------------
 参数值都为Number类型
 */
 // 参数 {'start':xx,'end':xxx}
 setYears:function(opt){
 this.eYear.innerHTML = '';
 for(var n=opt.start;n<=opt.end;n++){
 this.eYear.add(new Option(n,n));
 }
 },
 // 参数 {'start':xx,'end':xxx}
 // 参数 'end' 为可选,忽略,则开始到12月
 setMonths:function(opt){
 this.eMonth.innerHTML = '';
 var months = opt.end || 12;
 for(var n=opt.start;n<=months;n++){
 if(n<10) n = '0'+n;
 this.eMonth.add(new Option(n,n));
 }
 },
 // 参数 {'start':xx,'year':xxx,'month':xx,'star':xx,'end':xxx}
 // 参数 'end' 为可选,忽略,则开始到本月底(根据月份判断的)
 setDays:function(opt){
 this.eDay.innerHTML = '';
 var days = opt.end || this.getDays(opt.year,opt.month);
 for(var n=opt.start;n<=days;n++){
 if(n<10) n = '0'+n;
 this.eDay.add(new Option(n,n));
 }
 },
 /* 根据 年,月,返回正确的天数,如 2016-2,返回是29天(润年)
 --------------------------------------------------------------
 参数值都为Number类型
 */
 getDays:function(year,month){
 // var aDay = [31,28|29,31,30,31,30,31,31,30,31,30,31];
 // 二月份的天数数据处理
 var FedDays = year%4==0?29:28,
 returnDays = '';
 var month = month<10?month = '0'+month:month.toString();
 switch(month){
 case '01':
 case '03':
 case '05':
 case '07':
 case '08':
 case '10':
 case '12': returnDays = 31;break;
 case '04':
 case '06':
 case '09':
 case '11': returnDays = 30;break;
 case '02': returnDays = FedDays;break;
 }
 return returnDays;
 },
 /*工具辅助函数
 ----------------------------------
 */
 getId:function(id){
 return document.getElementById(id);
 }
}

效果展示图:

月份判定与性能优化

效果还不错吧,小伙伴们自己美化下,使用到自己的项目中去吧。

作者最新文章