共计 6397 个字符,预计需要花费 16 分钟才能阅读完成。
项目需要,需要一个日历表组件,产品狗嫌弃第三方提供的组件样式太丑,功能不全,带刀和产品理论奈何产品有枪。无奈只能自己写一个,发布完这条博客我就提离职,再也不和产品多 BB。
Html=>
`<template>
<div class="calender">
<div class="calender-title-wrapper">
<div class="calender-title">
<div class="calender-arrow-item left2" v-if="false"></div>
<div class="calender-arrow-item left1" @click="month--"></div>
<div class="calender-Date-text">{{year}}年 {{month}} 月 </div>
<div class="calender-arrow-item right1" @click="month++"></div>
<div class="calender-arrow-item right2" v-if="false"></div>
</div>
</div>
<div class="calender-content-wrapper">
<div class="calender-days-wrapper">
<div class="calender-days"> 日 </div>
<div class="calender-days"> 一 </div>
<div class="calender-days"> 二 </div>
<div class="calender-days"> 三 </div>
<div class="calender-days"> 四 </div>
<div class="calender-days"> 五 </div>
<div class="calender-days"> 六 </div>
</div>
<div class="calender-content">
<div class="calender-item-wrapper"
v-for="item in daysArr"
:class="{'no-current-day':item.month!=month,
active:item === clickItemObj,
currentDay:item.day===_CurrentDate.day&&
item.month===_CurrentDate.month&&
item.year===_CurrentDate.year}"@click="_clickDaysItem(item)"
>
<div class="calender-item">{{item.day}}</div>
<div class="tem-wrapper">
<span class="temp" v-for="d in markArr" :style="{background: d.color}" v-if="_visibleTemp(d,item)"></span>
</div>
</div>
</div>
<div class="calender-mask-wrapper">
<div class="calender-mask-item" v-for="item in markArr">
<span class="tem" :style="{background:item.color}"></span>
<span class="text">{{item.name}}</span>
</div>
</div>
</div>
</div>
</template>`
js=>
<script>
export default {
name: "calender",
props:{
markArr:{
type:Array,
default(){return []
}
}
},
data(){
return {
day:'',
month:'',
year:'',
currentDays:'',
daysArr:[],
clickItemObj:{}}
},
mounted() {this._getCurrentDate()
},
methods:{
// 点击日期
_clickDaysItem(item){
// 选中日期标记与解除标记
if(this.clickItemObj === item){this.clickItemObj = {}
}else {this.clickItemObj = item}
// 非当前月份跳转
if(item.month!=this.month){this.month = item.month}
// 传入事件筛选回返
this._user_defined_events(item)
},
//mark 渲染
_user_defined_events(item){for(let i=0;i<this.markArr.length;i++){if(this.markArr[i].days.includes(`${item.year}-${item.month}-${item.day}`)){this.$emit(this.markArr[i].clickEvent,item)
}
}
},
// 是否显示 mark
_visibleTemp(d,item){let dateStr = `${item.year}-${item.month}-${item.day}`
return d.days.includes(dateStr)
},
// 获取月份天数
_getDaysForMonth(year,month,type){let temp=new Date(year,month,type);
let day = new Date(temp.getTime() - 864e5).getDate();
this.currentDays = day
this._getFirstDaysForMonth(this.year,this.month)
},
// 获取当前日期
_getCurrentDate(){let date = new Date()
this.day = date.getDate()
this.month = date.getMonth()+1
this.year = date.getFullYear()
this._getDaysForMonth(this.year,this.month,1)
},
// 获取切换页月份第一天是周几与最后一天并获取月前与月后填补数组
_getFirstDaysForMonth(year,month){let weekdays = new Date(`${year}-${month}-01`).getDay()
let beforeMonthDaysArr = []
let currentMonthDaysArr = []
let afterMonthDaysArr = []
// 获取上一月总天数
if(month){let temp=new Date(year,month-1,1);
let day = new Date(temp.getTime() - 864e5).getDate();
for(let i=0;i<day;i++){
beforeMonthDaysArr.push({
year:year,
month:month-1,
day:i+1
})
}
beforeMonthDaysArr.splice(0,beforeMonthDaysArr.length-weekdays)
}else{//12 月}
// 获取当前月总天数
let temp=new Date(year,month,1);
let day = new Date(temp.getTime() - 864e5).getDate();
let afterWeekdays = new Date(`${year}-${month}-${day}`).getDay()
for(let i=0;i<day;i++){
currentMonthDaysArr.push({
year:year,
month:month,
day:i+1
})
}
if(beforeMonthDaysArr.length+currentMonthDaysArr.length+6-afterWeekdays===35){for(let i=0;i<13-afterWeekdays;i++){
afterMonthDaysArr.push({
year:year,
month:month+1,
day:i+1
})
}
}else{for(let i=0;i<6-afterWeekdays;i++){
afterMonthDaysArr.push({
year:year,
month:month+1,
day:i+1
})
}
}
this.daysArr = [...beforeMonthDaysArr,...currentMonthDaysArr,...afterMonthDaysArr]
// 获取下一月总天数
}
},
watch:{'month'(){if(this.month===0){
this.month = 12
this.year--
}
if(this.month===13){
this.month = 1
this.year++
}
this._getDaysForMonth(this.year,this.month,1)
}
},
computed:{_CurrentDate(){let date = new Date()
let {day,month ,year} = {day:date.getDate(),
month:date.getMonth()+1,
year:date.getFullYear()}
return {day,month ,year}
}
}
}
</script>
css=>
tips: 我用的 css 解析器是 stylus,用 less 和 sass 之类的大佬麻烦动动你们的小手加个花括号
<style scoped lang="stylus">
.calender
text-align center
min-width 280px
height 400px
.calender-title-wrapper
height 44px
line-height 44px
.calender-title
display flex
margin 0 auto
width 280px
.calender-arrow-item
flex 0 0 40px
cursor pointer
&.left1
background url("icon_left.svg") no-repeat center
&.left2
background url("icon_left2.svg") no-repeat center
&.right1
background url("icon_right.svg") no-repeat center
&.right2
background url("icon_right2.svg") no-repeat center
.calender-Date-text
flex 1
color #424242
font-size 16px
.calender-content-wrapper
.calender-days-wrapper
display flex
height 44px
line-height 44px
margin-bottom 11px
.calender-days
flex 1
color #A7A7A7
font-size 14px
.calender-content
.calender-item-wrapper
position relative
float left
width 14.285%
height 44px
line-height 44px
color #686868
cursor pointer
.tem-wrapper
position absolute
left 50%
height 10px
width 40px
transform translate3d(-50%,35px,0)
font-size 0
.temp
position relative
display inline-block
line-height 10px
width 6px
height 6px
background #4fff41
border-radius 3px
top -16px
margin 0 2px
.calender-item
position absolute
left calc(50% - 20px)
top calc(50% - 20px)
height 40px
width 40px
border-radius 20px
line-height 40px
&:hover
background #FFC912
&.no-current-day
color #DCDCDC
&.currentDay
color #ffffff
.calender-item
background #FFC912
&.active
color #ffffff
.calender-item
background #FFC912
.calender-mask-wrapper
height 37px
.calender-mask-item
height 37px
line-height 37px
width 25%
float left
.tem
margin-right 3px
display inline-block
height 8px
width 8px
border-radius 4px
.text
font-size 12px
</style>
给各位大佬呈上 APP.vue 中的调用,以及参数详细用法
App.vue 中的 @test1 事件是在在入参 markArr 中定义的,其中在 markArr 中 color 是标记日期的样式颜色,name 是显示的样式名称,days 是日期数组,clickEvent 就是自定义事件名称
<template>
<div id="app">
<calender
@test1="test"
:markArr="[
{
color:'#76ff19',
name:'测试一',
days:['2019-5-8','2019-5-11','2019-5-14','2019-5-22'],
clickEvent:'test1'
},
{
color:'#ff1323',
name:'测试二',
days:['2019-5-9','2019-5-11','2019-5-3','2019-5-1'],
clickEvent:'test2'
},
{
color:'#ffc518',
name:'测试三',
days:['2019-5-18','2019-5-11','2019-5-7','2019-5-4'],
clickEvent:'test3'
},
{
color:'#ff26fc',
name:'测试四',
days:['2019-5-28','2019-5-11','2019-5-30','2019-5-31'],
clickEvent:'test4'
}
]"
></calender>
<!--<backwards></backwards>-->
</div>
</template>
<script>
import calender from './components/calender/calender'
import backwards from './components/backwards/backwards'
export default {
name: 'App',
components:{
calender,
// backwards
},
methods:{test(item){console.log(item)
}
}
}
</script>
<style lang="stylus">
#app
position absolute
height 100%
width 100%
</style>
丢个成果图
是不是很丑?我故意的,想要好看自己改去吧,大致功能全都实现了
正文完
发表至: javascript
2019-05-08