初始化Swiper
初始化swiper主要有以下两点。
- 确定
每个swiper的范围 - 确定打开后
swiper的初始index
确定swiper slide
第一点比如说确定年份的最小年最大年范围,月份的最小月最大月,这里用三个对应的slide来分别表示。
// 年、月、日 slide列表
const [yearSlide, setYearSlide] = useState(null);
const [monthSlide, setMonthSlide] = useState(null);
const [daySlide, setDaySlide] = useState(null);
确定swiper index
第二点是根据传入的props确定起始日期,在确定打开后swiper的初始index所显示的值和起始日期对应。例如年份范围为1990到2025年,起始日期为2022年,那么打开后就要将初始值默认设置为2022所对应的index。这里用三个对应的index来表示。
// 初始的年、月、日index
const [yearIndex, setYearIndex] = useState(0);
const [monthIndex, setMonthIndex] = useState(0);
const [dayIndex, setDayIndex] = useState(0);
其他准备
除此之外在开始前,我们还要初始化三个swiper示例,方便我们获取到他们身上对应的属性和方法、一个初始化显示日期的变量以及一个控制date-picker显示的变量。
// date-picker 显示
const [showPicker, setShowPicker] = useState(false);
// 被选中的值
const [selectedValue, setSelectedValue] = useState('yyyy-mm-dd');
// swiper实例
const [yearSwiper, setYearSwiper] = useState(null);
const [monthSwiper, setMonthSwiper] = useState(null);
const [daySwiper, setDaySwiper] = useState(null);
生成最小、初始、最大日期所对应的年、月、日
校验并生成初始日期年、月、日
先考虑默认模式,首先要对传入的date进行校验,如果没传就设置为今天,如果传了就要校验格式是否正确,同时对计算前后年份范围的yearLength也进行校验。
/**
* 校验日期date和yearLength的正确性
* @param {*} date 初始日期
* @param {*} yearLength 年份值
*/
function verifyDate(date, yearLength) {
if(!(typeof date === 'string' && /\d{4}-\d{2}-\d{2}/.test(date))) {
return {
res: false,
msg: "您输入的date格式有误,请重新输入'yyyy-mm-dd'格式的date"
};
}
if(yearLength && typeof yearLength !== 'number') {
return {
res: false,
msg: "您输入的yearLength格式有误,请重新输入number类型的yearLength"
};
}
yearLength = yearLength ? yearLength : 50;
const { year, month, day } = splitDate(date);
if(year > year + yearLength || year < year - yearLength) {
return {
res: false,
msg: "您输入的年份不在合理范围内,请重新输入"
}
}
if(month > 12 || month === 0) {
return {
res: false,
msg: "您输入的月份不在合理范围内,请重新输入"
}
}
if(day > 31 || day === 0) {
return {
res: false,
msg: "您输入的日期不在合理范围内,请重新输入"
}
}
return { res: true, verifyLength: yearLength };
}
// 根据校验结果生成初始日期,并且将初始日期的年、月、日分别解出来
const today = new Date();
// 获取默认日期
let initialDate = "";
if(date) {
const { res, msg, verifyLength } = verifyDate(date, yearLength);
if(res === true) {
initialDate = date;
yearLength = verifyLength;
} else {
errorHandler(msg);
return false;
}
} else {
// 默认日期等于今天
initialDate = moment(today).format('YYYY-MM-DD');
yearLength = yearLength ? yearLength : 10;
}
const { year: initYear, month: initMonth, day: initDay } = splitDate(initialDate);
根据初始日期生成最大,最小日期年、月、日
生成最大最小日期后要对初始值是否在二者之间进行校验,因为初始值是用户输入的满足要求的合理日期值,可能超出范围进而导致后面生成slide报错。
// 获取最大日期
let maxDate = moment(today).add(yearLength, 'year').format('YYYY-MM-DD');
const { year: maxYear, month: maxMonth, day: maxDay } = splitDate(maxDate);
console.log('--最大日期maxDate--', maxYear, maxMonth, maxDay);
// 获取最小日期
let minDate = moment(today).subtract(yearLength, 'year').format('YYYY-MM-DD');
const { year: minYear, month: minMonth, day: minDay } = splitDate(minDate);
console.log('--最小日期minDate--', minYear, minMonth, minDay);
// 校验默认日期是否在最小日期和最大日期之内(这里校验过以下就无需校验,省掉大量代码)
const checkRes = moment(initialDate).isBetween(minDate, maxDate, null, "[]");
if(!checkRes) {
errorHandler('您配置的initialDate超出了合理范围,请重新配置。')
return false;
}
生成年份slide => yearSlide
这里为了对slide进行统一处理,定义了一个公共方法
/**
* 生成swiper的slide
* @param {string} type // slide类型 年 | 月 | 日 | 时 | 分
* @param {number} endDay // 截止日期
* @param {number} startDay // 开始日期
*/
function generateSlide(type, endDay, startDay = 0) {
let arr = [];
const todayYear = new Date().getFullYear();
switch(type) {
case("year"):
endDay = endDay ? endDay : todayYear + 50;
// 如果startDay不是0,则endDay加1,保证循环的数据的正确
if(startDay) endDay++;
break;
case("month"):
endDay = endDay ? endDay : 12;
// 如果startDay不是0,则endDay加1,保证循环的数据的正确
if(startDay) endDay++;
break;
case("day"):
endDay = endDay ? endDay : 31;
// 如果startDay不是0,则endDay加1,保证循环的数据的正确
if(startDay) endDay++;
break;
case("hour"):
endDay = endDay ? endDay : 24;
break;
case("minute"):
endDay = endDay ? endDay : 12;
break;
}
for(var i = startDay; i < endDay; i++){
arr.push({
value: startDay === 0 ? i + 1 : i, // 如果是从0开始需要+1,如果不是则不需要
key: type + i,
});
}
return arr;
}
/**
* 当start不传时,默认为0,循环时每一项为 i + 1,例如第0项的值为1
* 当start传了时明显不能这么循环,因此将循环的每一项变为i,最大值加1,来保证循环数据正确
* 例如从12循环到31, 12 <= i < 32
*/
使用该方法生成年份的slide,将最小年,最大年传入即可。
const yearSlideInit = generateSlide('year', maxYear, minYear);
生成年份对应的index => yearIndex
年份的index很好生成,举个🌰。
[1996, 2012] 1996年的index为0; 2000年的index为4。
因此,index为初始年份减去最小年份。
const yearIndexInit = initYear - minYear;