【JS】实现一个简单的日历输入组件

日历组件

【JS】实现一个简单的日历输入组件

日历组件在平时项目中是非常常见的一个组件,那么我们就来实现一下。实现之前要知道有哪几个需要注意的点。
-一、日期要怎么显示?
每个月需要展示不同的日期,那么我们就来找找规律吧。
1.每个月需要展示固定的42天。
2.每个月的一号是周几,比如上图中的一号是周二,那么我们可以使用时间的getDay函数获取一号的是2,然后让第一天往前推2天,就是我们需要展示在日历上的第一天了。

  • 二、日期框里的年月不能根据输入框里的日期变化,因为后面还会涉及到切换问题
  • 三、每次切换都要更新日历板中的日期,使其与对应月份展示的相同
  • 四、每次点击日历中的日期需要隐藏日历板(点击切换年月按钮不隐藏)
  • 五、点击日历板上的日期之后再次点击输入框会展示对应月份对应时间,对应时间需要给一个特殊展示(如上图蓝色部分)
  • 六、不是当月的时间需要和当前月的日期有区分(颜色区分)
  • 七、选中了某一天需要更新父组件中的数据
  • 八、输入框中录入年月日,点击enter键,再次点击input会弹出对应的日期并且标蓝色

上面就是封装这个日历所需要注意到的点,那么下面看代码吧;

代码实现

父组件

<template>

<div id="datePicker">

<Calendar :time="time" v-model="time"></Calendar>

<div>{{time}}</div>

</div>

</template>

<script>

import Calendar from '../components/calendar';

export default {

name: 'datePicker',

components: {

Calendar

},

data() {

return {

time: new Date()

};

},

methods: {}

};

</script>

<style>

</style>

子组件

<template>

<div id="calendar" v-click-outside>

<input type="text" ref="input" class="input" :value="formatterTime" @focus="handlClick" @keydown="enterInput">

<div class="content" v-if="isShow">

<div class="title">

<div class="oper">

<span class="iconfont icon-shuangjiantouzuo" @click="handlChangeDate('year',-1)"></span>

<span class="iconfont icon-zuojiantou" @click="handlChangeDate('month',-1)"></span>

</div>

<div class="date">{{`${timeCopy.year}年${timeCopy.month}月`}}</div>

<div class="oper">

<span class="iconfont icon-youjiantou" @click="handlChangeDate('month',+1)"></span>

<span class="iconfont icon-shuangjiantouyou" @click="handlChangeDate('year',+1)"></span>

</div>

</div>

<div class="week">

<span class="week-item" v-for="(v,i) in weekList" :key="i">{{v}}</span>

</div>

<ul class="days">

<li class="days-row" v-for="(v,i) in 6" :key="i">

<span class="days-item" v-for="(vs,j) in 7" :key="j"

@click="chooseDay(getCurrentMonthDays[i*7+j])"

:class="[

{'gray-day':getCurrentMonthDays[i*7+j].getMonth()+1!=timeCopy.month},

{'high-light':getCurrentMonthDays[i*7+j].getDate()==timeCopy.day}

]"

>

{{getCurrentMonthDays[i*7+j].getDate()}}

</span>

</li>

</ul>

</div>

</div>

</template>

<script>

export default {

name: 'calendar',

props: {

time: {type: Date}

},

directives: {

'clickOutside': {

bind(el, builing, vNode) {

let handler = (e) => {

let input = document.getElementsByClassName('input')[0];

let title = document.getElementsByClassName('title')[0];

if (!title) return;

if (!input.contains(e.target) && !title.contains(e.target)) {

vNode.context.isShow = false;

}

};

document.addEventListener('click', handler);

}

}

},

computed: {

formatterTime() {

let {year, month, day} = this.timeCopy;

return `${year}-${month}-${day}`;

},

getCurrentMonthDays() {

let {year, month} = this.timeCopy;

let firstDay = new Date(`${year}-${month}-01`);

let week = firstDay.getDay();

let beginDay;

if (week === 0) {

beginDay = firstDay - 7 * 1000 * 60 * 60 * 24;

} else {

beginDay = firstDay - week * 1000 * 60 * 60 * 24;

}

let dateArr = [];

for (let i = 0; i < 42; i++) {

dateArr.push(new Date(beginDay + i * 1000 * 60 * 60 * 24));

}

return dateArr;

}

},

data() {

return {

isShow: false,

timeCopy: {},

weekList: ['日', '一', '二', '三', '四', '五', '六']

};

},

methods: {

enterInput(e) {

if (e.keyCode == '13') {

let val = e.srcElement.value;

let {month, day} = this.setData(new Date(val));

if (isNaN(month) || isNaN(day)) {

alert('输入不合法哦');

return;

}

this.timeCopy = this.setData(new Date(e.srcElement.value));

this.$emit('input', new Date(e.srcElement.value));

this.isShow = false;

this.$refs.input.blur();

}

},

handlChangeDate(flag, val) {

this.timeCopy[flag] += val;

if (this.timeCopy.month > 12) {

this.timeCopy.month = 1;

this.timeCopy.year += 1;

}

if (this.timeCopy.month < 1) {

this.timeCopy.month = 12;

this.timeCopy.year -= 1;

}

},

chooseDay(date) {

this.$emit('input', date);

this.timeCopy = this.setData(date);

},

setData(time) {

let year = time.getFullYear();

let month = time.getMonth() + 1;

let day = time.getDate();

return {year, month, day};

},

handlClick() {

this.isShow = true;

}

},

created() {

this.timeCopy = this.setData(this.time);

}

};

</script>

<style lang="less" scoped>

* {

margin: 0;

padding: 0;

}

ul li {

list-style: none;

}

#calendar {

@commonColor: #00a0ff;

text-align: center;

display: inline-block;

input {

width: 268px;

background-color: #fff;

border-radius: 4px;

border: 1px solid #dcdfe6;

color: #606266;

height: 40px;

line-height: 40px;

outline: none;

padding: 0 15px;

}

.content {

user-select: none;

position: absolute;

width: 300px;

z-index: 100;

background: #fff;

color: #606266;

border: 1px solid #e4e7ed;

box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);

border-radius: 4px;

line-height: 30px;

margin: 5px 0;

.title {

display: flex;

height: 25px;

line-height: 25px;

margin-bottom: 15px;

.oper {

font-size: 16px;

cursor: pointer;

flex: 1;

}

.date {

flex: 1;

}

}

.week {

display: flex;

border-bottom: 1px solid #bfc4cc;

.week-item {

flex: 1;

font-size: 14px;

}

}

.days {

display: flex;

flex-direction: column;

padding: 5px;

font-size: 12px;

justify-content: space-evenly;

.days-row {

display: flex;

.days-item {

flex: 1;

cursor: pointer;

&:hover {

color: @commonColor;

}

}

}

}

}

.gray-day {

color: #bfc4cc !important;

}

.high-light {

color: @commonColor;

}

}

</style>

以上是 【JS】实现一个简单的日历输入组件 的全部内容, 来源链接: utcz.com/a/94329.html

回到顶部