当前位置:网站首页>Write a mobile date selector component by yourself
Write a mobile date selector component by yourself
2022-07-04 09:35:00 【Dandelion_ drq】
List of articles
background
The component written in this article is based on uni-app Under the framework of , But in fact, the framework is not important , It's all the same .
Some students may ask ,uni-app It doesn't exist in itself picker,mode=time Is the time selector when , Why write one by yourself ? That's because our product boss said , Don't fix it at the bottom to pop up the selected , Want to nest in the page filter , Because considering interaction blabla Of …… I thought about it , ok , Give time to say everything , Let's build a wheel by ourselves ~
Effect demonstration
Let's see the effect first ~
- Full functionality

- Year month day mode

- Year month day hour minute second mode

- Month month mode

Ideas
Before starting to work, first brush your mind .
The date filter interaction on the mobile end is more common, which is multi column scrolling , So we can use picker-view To achieve . In addition to basic interaction , The point that components need to pay attention to is the correlation between month, year and day , such as 1 Monthly 31 God ,4 Month is 30 God , Leap year 2 Month is 29 God wait for this , That is, the month, year and day need to be interrelated and dynamic . In addition, you can add the maximum and minimum time range for supporting configuration , Support switching between different time modes ( For example, mm / DD / yyyy / years / Mm / DD / yyyy HHM / S ) etc. .
The main functions of a commonly used date selector component are the above .
For the full code, see :https://github.com/Dandelion-drq/uniapp-datetime-picker
Welcome to my favorite friend star Ha ~
Realization
1. picker-view Realize basic interaction
First encapsulate a multi column scrolling selection component that accepts multiple arrays , It is convenient to support different date mode switching later .
<template>
<picker-view class="picker-view" :value="indexArr" @change="onChange">
<picker-view-column class="picker-view-column" v-for="(col, colIdx) in columns" :key="colIdx">
<view v-for="(item, idx) in col" :key="idx">{
{ item }}</view>
</picker-view-column>
</picker-view>
</template>
<script src="./index.js"></script>
<style lang="css" scoped src="./index.css"></style>
.picker-view {
height: 356rpx;
}
.picker-view-column {
font-size: 14px;
line-height: 34px;
text-align: center;
color: #333;
}
export default {
data() {
return {
};
},
props: {
// All column option data
columns: {
type: Array,
default: () => []
},
// The default selected value array for each column , The first item is selected by default
selectVals: {
type: Array,
default: () => []
}
},
computed: {
// Index of selected items in each column , When the default selection value changes, this value also changes
indexArr: {
// Multidimensional arrays , Deep monitoring
cache: false,
get() {
// console.log('indexArr', this.selectVals, this.columns);
if (this.selectVals.length > 0) {
return this.columns.map((col, cIdx) => {
return col.findIndex((i) => i == this.selectVals[cIdx]);
});
} else {
return [].fill(0, 0, this.columns.length);
}
}
}
},
methods: {
onChange(e) {
const {
value } = e.detail;
// console.log('pickerview change ', value, this.columns);
let ret = this.columns.map((item, index) => {
let idx = value[index];
if (idx < 0) {
idx = 0;
}
if (idx > item.length - 1) {
idx = item.length - 1;
}
return item[idx];
});
// console.log(' Selected value ', ret);
this.$emit('onChange', {
value: ret
});
}
}
};
2. Dynamic configuration of year, month and day, and support the maximum and minimum dates
The year is relatively simple , It is good to generate an array from the configured minimum date year to the maximum date year . Pay attention to the month when the selected year happens to be the smallest / The year of the maximum optional date , The month should start from the smallest / The maximum optional date starts / end , Other months are 1~12. First, list the number of days per person in a normal year , Then pay attention to leap years 2 Month is 29 God , Also, like the month, it should be noted that if the selected year and month happen to be the smallest / The year, month and hour of the maximum optional date , From the smallest / The maximum optional date starts / end . The same goes for hours, minutes and seconds .
<template>
<view class="datetime-picker">
<CustomPickerView :columns="dateConfig" :selectVals="selectVals" @onChange="onChangePickerValue" />
</view>
</template>
<script src="./index.js"></script>
import CustomPickerView from '../customPickerView/index.vue';
import DateUtil from '../dateTimePicker/dateUtil';
export default {
components: {
CustomPickerView
},
data() {
return {
selectYear: new Date().getFullYear(),
selectMonth: new Date().getMonth() + 1, // Selected month ,1~12
selectDay: new Date().getDate(),
selectHour: new Date().getHours(),
selectMinute: new Date().getMinutes(),
selectSecond: new Date().getSeconds()
};
},
props: {
// Optional minimum date , Default ten years ago
minDate: {
type: String,
default: ''
},
// Optional maximum date , Default ten years later
maxDate: {
type: String,
default: ''
}
},
computed: {
minDateObj() {
let minDate = this.minDate;
if (minDate) {
if (this.mode == 2 && minDate.replace(/\-/g, '/').split('/').length == 2) {
// When the date mode is year / month, it may be transmitted minDate yes 2022-02 This format , stay ios Next new Date Will report a mistake , Add the date part to make it compatible
minDate += '-01';
}
return new Date(DateUtil.handleDateStr(minDate));
} else {
// No minimum date is sent , Default ten years ago
minDate = new Date();
minDate.setFullYear(minDate.getFullYear() - 10);
return minDate;
}
},
maxDateObj() {
let maxDate = this.maxDate;
if (maxDate) {
if (this.mode == 2 && maxDate.replace(/\-/g, '/').split('/').length == 2) {
// When the date mode is year / month, it may be transmitted maxDate yes 2022-02 This format , stay ios Next new Date Will report a mistake , Add the date part to make it compatible
maxDate += '-01';
}
return new Date(DateUtil.handleDateStr(maxDate));
} else {
// No minimum date is sent , Default ten years later
maxDate = new Date();
maxDate.setFullYear(maxDate.getFullYear() + 10);
return maxDate;
}
},
years() {
let years = [];
let minYear = this.minDateObj.getFullYear();
let maxYear = this.maxDateObj.getFullYear();
for (let i = minYear; i <= maxYear; i++) {
years.push(i);
}
return years;
},
months() {
let months = [];
let minMonth = 1;
let maxMonth = 12;
// If the selected year happens to be the year of the minimum optional date , The month should start from the month of the minimum date
if (this.selectYear == this.minDateObj.getFullYear()) {
minMonth = this.minDateObj.getMonth() + 1;
}
// If the selected year happens to be the year of the maximum optional date , That month will end in the month of the maximum date
if (this.selectYear == this.maxDateObj.getFullYear()) {
maxMonth = this.maxDateObj.getMonth() + 1;
}
for (let i = minMonth; i <= maxMonth; i++) {
months.push(i);
}
return months;
},
days() {
// In a year 12 The number of days of each month
let monthDaysConfig = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
// Leap year 2 Monthly 29 God
if (this.selectMonth == 2 && this.selectYear % 4 == 0) {
monthDaysConfig[1] = 29;
}
let minDay = 1;
let maxDay = monthDaysConfig[this.selectMonth - 1];
if (this.selectYear == this.minDateObj.getFullYear() && this.selectMonth == this.minDateObj.getMonth() + 1) {
minDay = this.minDateObj.getDate();
}
if (this.selectYear == this.maxDateObj.getFullYear() && this.selectMonth == this.maxDateObj.getMonth() + 1) {
maxDay = this.maxDateObj.getDate();
}
let days = [];
for (let i = minDay; i <= maxDay; i++) {
days.push(i);
}
return days;
},
hours() {
let hours = [];
let minHour = 0;
let maxHour = 23;
if (
this.selectYear == this.minDateObj.getFullYear() &&
this.selectMonth == this.minDateObj.getMonth() + 1 &&
this.selectDay == this.minDateObj.getDate()
) {
minHour = this.minDateObj.getHours();
}
if (
this.selectYear == this.maxDateObj.getFullYear() &&
this.selectMonth == this.maxDateObj.getMonth() + 1 &&
this.selectDay == this.maxDateObj.getDate()
) {
maxHour = this.maxDateObj.getHours();
}
for (let i = minHour; i <= maxHour; i++) {
hours.push(i);
}
return hours;
},
minutes() {
let mins = [];
let minMin = 0;
let maxMin = 59;
if (
this.selectYear == this.minDateObj.getFullYear() &&
this.selectMonth == this.minDateObj.getMonth() + 1 &&
this.selectDay == this.minDateObj.getDate() &&
this.selectHour == this.minDateObj.getHours()
) {
minMin = this.minDateObj.getMinutes();
}
if (
this.selectYear == this.maxDateObj.getFullYear() &&
this.selectMonth == this.maxDateObj.getMonth() + 1 &&
this.selectDay == this.maxDateObj.getDate() &&
this.selectHour == this.maxDateObj.getHours()
) {
maxMin = this.maxDateObj.getMinutes();
}
for (let i = minMin; i <= maxMin; i++) {
mins.push(i);
}
return mins;
},
seconds() {
let seconds = [];
let minSecond = 0;
let maxSecond = 59;
if (
this.selectYear == this.minDateObj.getFullYear() &&
this.selectMonth == this.minDateObj.getMonth() + 1 &&
this.selectDay == this.minDateObj.getDate() &&
this.selectHour == this.minDateObj.getHours() &&
this.selectMinute == this.minDateObj.getMinutes()
) {
minSecond = this.minDateObj.getSeconds();
}
if (
this.selectYear == this.maxDateObj.getFullYear() &&
this.selectMonth == this.maxDateObj.getMonth() + 1 &&
this.selectDay == this.maxDateObj.getDate() &&
this.selectHour == this.maxDateObj.getHours() &&
this.selectMinute == this.maxDateObj.getMinutes()
) {
maxSecond = this.maxDateObj.getSeconds();
}
for (let i = minSecond; i <= maxSecond; i++) {
seconds.push(i);
}
return seconds;
}
}
}
// DateUtil.js
/** * Date time format * @param {Date} date Date object to format * @param {String} fmt Formatted string ,eg:YYYY-MM-DD HH:mm:ss * @returns Formatted date string */
function formatDate(date, fmt) {
if (typeof date == 'string') {
date = new Date(handleDateStr(date));
}
var o = {
'M+': date.getMonth() + 1, // month
'd+': date.getDate(), // Japan
'D+': date.getDate(), // Japan
'H+': date.getHours(), // Hours
'h+': date.getHours(), // Hours
'm+': date.getMinutes(), // branch
's+': date.getSeconds(), // second
'q+': Math.floor((date.getMonth() + 3) / 3), // quarter
S: date.getMilliseconds() // millisecond
};
if (/([y|Y]+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').slice(4 - RegExp.$1.length));
}
for (var k in o) {
if (new RegExp('(' + k + ')').test(fmt)) {
fmt = fmt.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ('00' + o[k]).slice(('' + o[k]).length));
}
}
return fmt;
}
/** * Processing time string , compatible ios Next new Date() return NaN problem * @param {*} dateStr Date string * @returns */
function handleDateStr(dateStr) {
return dateStr.replace(/\-/g, '/');
}
/** * Date of judgment 1 Is it on the date 2 Before , That is, the date 1 Less than date 2 * @param {Date} date1 * @param {Date} date2 * @returns */
function isBefore(date1, date2) {
if (typeof date1 == 'string') {
date1 = new Date(handleDateStr(date1));
}
if (typeof date2 == 'string') {
date2 = new Date(handleDateStr(date2));
}
return date1.getTime() < date2.getTime();
}
/** * Date of judgment 1 Is it on the date 2 after , That is, the date 1 Greater than date 2 * @param {Date} date1 * @param {Date} date2 * @returns */
function isAfter(date1, date2) {
if (typeof date1 == 'string') {
date1 = new Date(handleDateStr(date1));
}
if (typeof date2 == 'string') {
date2 = new Date(handleDateStr(date2));
}
return date1.getTime() > date2.getTime();
}
export default {
formatDate,
handleDateStr,
isBefore,
isAfter
};
3. Support different date modes
Support many different date modes , Including mm / DD / yyyy ( Default )、 years 、 year 、 Mm / DD / yyyy HHM / S . The main processing logic is based on mode The change of , To dynamically generate and transmit to pickerView An array of components , And its default selected value , And notice pickerView Components onChange The processing of events also needs to consider different date patterns .
<template>
<view class="datetime-picker">
<PickerView :columns="dateConfig" :selectVals="selectVals" @onChange="onChangePickerValue" />
</view>
</template>
<script src="./index.js"></script>
<style scoped></style>
{
props: {
// Date mode ,1: Specific date ,2: years ,3: year ,4: Mm / DD / yyyy HHM / S
mode: {
type: Number,
default: 1
},
// The default selected date ( Note that it should correspond to the date pattern )
defaultDate: {
type: String,
default: ''
}
}
computed: {
// Pass to pickerView An array of components , according to mode To generate different data
dateConfig() {
if (this.mode == 2) {
// Month month mode
let years = this.years.map((y) => y + ' year ');
let months = this.months.map((m) => m + ' month ');
return [years, months];
} else if (this.mode == 3) {
// Only year mode
let years = this.years.map((y) => y + ' year ');
return [years];
} else if (this.mode == 4) {
// Year month day hour minute second mode
let years = this.years.map((y) => y + ' year ');
let months = this.months.map((m) => m + ' month ');
let days = this.days.map((d) => d + ' Japan ');
let hours = this.hours.map((h) => h + ' when ');
let minutes = this.minutes.map((m) => m + ' branch ');
let seconds = this.seconds.map((s) => s + ' second ');
return [years, months, days, hours, minutes, seconds];
} else {
// Default , Year month day mode
let years = this.years.map((y) => y + ' year ');
let months = this.months.map((m) => m + ' month ');
let days = this.days.map((d) => d + ' Japan ');
return [years, months, days];
}
},
// pickerView The default value is , according to mode To change the value
selectVals() {
if (this.mode == 2) {
return [this.selectYear + ' year ', this.selectMonth + ' month '];
} else if (this.mode == 3) {
return [this.selectYear + ' year '];
} else if (this.mode == 4) {
return [
this.selectYear + ' year ',
this.selectMonth + ' month ',
this.selectDay + ' Japan ',
this.selectHour + ' when ',
this.selectMinute + ' branch ',
this.selectSecond + ' second '
];
} else {
return [this.selectYear + ' year ', this.selectMonth + ' month ', this.selectDay + ' Japan '];
}
}
},
methods: {
onChangePickerValue(e) {
const {
value } = e;
// console.log('onChangePickerValue', value);
if (this.mode == 2 && value[0] && value[1]) {
// Month month mode
this.selectYear = Number(value[0].replace(' year ', ''));
this.selectMonth = Number(value[1].replace(' month ', ''));
} else if (this.mode == 3 && value[0]) {
// Only year mode
this.selectYear = Number(value[0].replace(' year ', ''));
} else if (this.mode == 4 && value[0] && value[1] && value[2] != '' && value[3] && value[4] && value[5]) {
// Year month day hour minute second mode
this.selectYear = Number(value[0].replace(' year ', ''));
this.selectMonth = Number(value[1].replace(' month ', ''));
this.selectDay = Number(value[2].replace(' Japan ', ''));
this.selectHour = Number(value[3].replace(' when ', ''));
this.selectMinute = Number(value[4].replace(' branch ', ''));
this.selectSecond = Number(value[5].replace(' second ', ''));
} else if (value[0] && value[1] && value[2]) {
// Default , Year month day mode
this.selectYear = Number(value[0].replace(' year ', ''));
this.selectMonth = Number(value[1].replace(' month ', ''));
this.selectDay = Number(value[2].replace(' Japan ', ''));
} else {
// Other situations may be pickerView There is a problem with the returned data , Don't deal with
console.log('onChangePickerValue Other situations ');
return;
}
let formatTmpl = 'YYYY-MM-DD';
if (this.mode == 2) {
formatTmpl = 'YYYY-MM';
} else if (this.mode == 3) {
formatTmpl = 'YYYY';
} else if (this.mode == 4) {
formatTmpl = 'YYYY-MM-DD HH:mm:ss';
}
this.$emit(
'onChange',
DateUtil.formatDate(
new Date(`${
this.selectYear}/${
this.selectMonth}/${
this.selectDay} ${
this.selectHour}:${
this.selectMinute}:${
this.selectSecond}`),
formatTmpl
)
);
}
}
}
Completed the above 3 spot , The date selector component is written , Complete code and use demo see :https://github.com/Dandelion-drq/uniapp-datetime-picker
Welcome to my favorite friend star~
边栏推荐
- At the age of 30, I changed to Hongmeng with a high salary because I did these three things
- IIS configure FTP website
- 2022-2028 global elastic strain sensor industry research and trend analysis report
- Reading notes on how to connect the network - hubs, routers and routers (III)
- 【leetcode】540. A single element in an ordered array
- How does idea withdraw code from remote push
- Svg image quoted from CodeChina
- PHP book borrowing management system, with complete functions, supports user foreground management and background management, and supports the latest version of PHP 7 x. Database mysql
- Write a jison parser from scratch (6/10): parse, not define syntax
- Development trend and market demand analysis report of high purity tin chloride in the world and China Ⓔ 2022 ~ 2027
猜你喜欢

Nurse level JDEC addition, deletion, modification and inspection exercise

How to ensure the uniqueness of ID in distributed environment

Dede plug-in (multi-function integration)

GoLand environment variable configuration

Opencv environment construction (I)

You can see the employment prospects of PMP project management

HMS core helps baby bus show high-quality children's digital content to global developers

PHP personal album management system source code, realizes album classification and album grouping, as well as album image management. The database adopts Mysql to realize the login and registration f

Sort out the power node, Mr. Wang he's SSM integration steps

The child container margin top acts on the parent container
随机推荐
How do microservices aggregate API documents? This wave of show~
Problems encountered by scan, scanf and scanln in golang
MySQL foundation 02 - installing MySQL in non docker version
2022-2028 global gasket metal plate heat exchanger industry research and trend analysis report
GoLand environment variable configuration
Markdown syntax
lolcat
Sword finger offer 30 contains the stack of Min function
PMP registration process and precautions
Function comparison between cs5261 and ag9310 demoboard test board | cost advantage of cs5261 replacing ange ag9310
Lauchpad X | 模式
Explanation of closures in golang
Solve the problem of "Chinese garbled MySQL fields"
Write a jison parser from scratch (2/10): learn the correct posture of the parser generator parser generator
Write a jison parser from scratch (5/10): a brief introduction to the working principle of jison parser syntax
PHP student achievement management system, the database uses mysql, including source code and database SQL files, with the login management function of students and teachers
165 webmaster online toolbox website source code / hare online tool system v2.2.7 Chinese version
Ultimate bug finding method - two points
Launpad | Basics
2022-2028 global probiotics industry research and trend analysis report