ant框架年份组件
看了ant框架针对于年份不能自定义插槽内容所以放弃用ant框架年份组件,自定义插槽内容是想实现年份下方可以加小圆点的需求,因加小圆点需求必须实现,决定自己封装组件来实现需求,自己实现的效果呢类似于ant年份控件 在这里做一下记录。
效果图如下:
1.YearPicker.vue
<template>
<div class="year-picker" >
<q-input
outlined
v-model="contentValue"
dense
@blur="blurEvent"
@focus="inputFocus"
placeholder="选择年份"
clearable
@clear="clearHandle"
class="col"
>
</q-input>
<transition name="fade">
<div class="year-picker__year-box" v-if="showYearContent">
<div class="year-picker__year-title">
<span class="to-left" @click="toLeft()"><DoubleLeftOutlined style="rgba(0, 0, 0, 0.45)"/></span>
<span class="to-middle">{{yearStart}}-{{yearEnd-1}}</span>
<span class="to-right" @click="toRight()"><DoubleRightOutlined style="rgba(0, 0, 0, 0.45)"/></span>
</div>
<div class="year-picker__year-content" >
<span v-for="(item,index) in yearList" :key="index" style="position: relative;">
<div class="listItem" :class="{listItemBgC: item === checkedIndex,'year-disable':yearDis(item)}" @click="chooseYear(item,index)">{{item}}</div>
<div :class="getAllYear(item)" ></div>
</span>
</div>
</div>
</transition>
</div>
</template>
<script>
import { ref, shallowRef, watch, nextTick, onMounted, inject,reactive ,computed,toRefs,getCurrentInstance,watchEffect} from 'vue'
import {DoubleLeftOutlined,DoubleRightOutlined} from '@ant-design/icons-vue'
export default {
name: 'index',
components:{
DoubleLeftOutlined,
DoubleRightOutlined
},
props: {
yearDisable: {
type: String,
default: 'no'
},
contentValue: {
type: Number,
},
allDataList:{
type: Array,
default: ()=>{
return []
}
},
},
setup(props,context) {
const { yearDisable } = toRefs(props);
const checkedIndex = ref()
const state = reactive({
yearLists: [],
showYearContent: false,
yearStart: 2010,
yearEnd: 2030,
blurIndex:null,
allDataList:[],
})
const contentValue = ref()
watch(() => props.contentValue, (newvalue) => {
if(newvalue){
contentValue.value = newvalue
context.emit('handlerInput',newvalue)
}
}, {immediate: true})
watch(() => props.allDataList, (value) => {
if(!value) return
state.allDataList = value
}, {immediate: true})
const inputFocus = ()=> {
state.showYearContent = true
}
const blurEvent= (e)=> {
state.showYearContent = false
}
const chooseYear=(year,index)=> {
if (year > yearDis.value) return
state.showYearContent = false
checkedIndex.value = year
context.emit('handlerInput', year)
}
const toLeft=()=> {
state.yearStart -= 20
state.yearEnd -= 20
state.showYearContent = true
}
const toRight=()=> {
state.yearStart += 20
state.yearEnd += 20
state.showYearContent = true
}
const yearDis = computed(()=>{
return function (y) {
switch (yearDisable.value) {
case 'before': {
return y < new Date().getFullYear()
}
break;
case 'no': {
return false
}
break;
case 'after': {
return y > new Date().getFullYear()
}
}
}
})
const yearList = computed(()=>{
let arr = []
for (let i = state.yearStart; i < state.yearEnd; i++) {
arr.push(i)
}
return arr
})
const clearHandle = (value)=>{
checkedIndex.value = ''
}
//实现年份下方加小圆点事件
const getAllYear = (year) => {
if(state.allDataList.findIndex(mon => mon === year) !== -1){
return 'checkbox1'
}else{
return 'defultbox1'
}
}
return {
...toRefs(state),
yearDis,
getAllYear,
yearList,
checkedIndex,
clearHandle,
inputFocus,
contentValue,
blurEvent,
chooseYear,
toLeft,
toRight,
}
},
}
</script>
<style scoped lang="scss">
.checkbox1{
position: absolute;
left: 50%;
height: 5px;
width: 8px;
border-radius: 5px;
background-color: #ff9800;
transform: translate3d(-50%,0,0)
}
.defultbox1{
position: absolute;
left: 50%;
height: 5px;
width: 8px;
border-radius: 5px;
}
.year-picker {
::v-deep(.q-field--dense .q-field__control){
height: 32px!important;
}
::v-deep(.q-field--dense .q-field__marginal){
height: 32px!important;
}
.col{
box-sizing: border-box;
margin: 0;
color: rgba(0, 0, 0, 0.88);
font-size: 14px;
height: 32px!important;
position: relative;
display: inline-flex;
align-items: center;
background: #ffffff;
border-radius: 6px;
transition: border 0.2s,box-shadow;
}
.col:hover{
border: none!important;
margin: 0;
}
margin-left: 20px;
display: inline-block;
border-radius: 5px;
.year-picker__icon {
position: absolute;
transform: translate(-26px, 10px);
color: #d9d9d9
}
.year-picker__input--real:hover {
border: 1px solid rgba(0, 122, 244, 0.8);
}
.year-picker__year-title {
height: 40px;
width: 270px;
border-top: 1px solid #d4d4d4;
border-bottom: 1px solid #d4d4d4;
display: flex;
justify-content: space-around;
align-items: center;
.to-middle{
font-weight: bold;
color: #666666;
}
span {
color: #525252;
cursor: pointer;
}
span:active {
opacity: .5;
}
}
.year-picker__year-box {
position: absolute;
z-index: 10;
background: #ffffff;
border-radius: 5px;
border: 1px solid #eeeeee;
box-shadow: 0 0 .38rem 0 rgba(0, 0, 0, 0.1);
transform: translateY(-32px);
left:36px;
top:72px;
}
.year-picker__year-content {
padding-top: 20px;
width: 270px;
height: 250px;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
.listItem{
color: #525252;
font-size: 14px;
width: 48px;
height: 25px;
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 2px;
}
.listItem:hover{
cursor: pointer;
}
.listItemBgC{
background-color: #0067c0;
color:white;
border-radius: 3px;
}
.year-disable {
background: #f5f5f5;
}
.year-disable:hover {
cursor: no-drop;
background: #f5f5f5;
}
}
}
.fade-enter,
.fade-leave-to {
opacity: 0;
transform: translateY(-30px);
}
/* 过程 */
.fade-enter-active {
transition: all 0.5s;
}
/* 结束 */
.fade-enter-to {
opacity: 1;
}
.fade-leave-active {
transition: all 0.5s;
}
.dark {
border: 1px solid blue;
color: #8099b3;
.year-picker__input {
background: #003366;
color: #8099b3;;
}
.year-picker__input--real {
border: 1px solid blue;
height: 32px;
}
.year-picker__input::placeholder {
color: #1c5389;
}
.year-picker__year-title {
border-top: 1px solid blue;
border-bottom: 1px solid blue;
span {
color: #8099b3;
}
}
.year-text:hover {
cursor: pointer;
background: rgba(157, 219, 252, 0.41);
border-radius: 3px;
}
.year-picker__year-content {
.year-text {
color: #8099b3;
}
.year-disable {
background: #133558;
}
.year-disable:hover {
cursor: no-drop;
background: #133558;
}
}
}
</style>
vue 使用组件
<YearPicker :contentValue="contentValue" @handlerInput="handlerInput" :year-disable="'no'" :allDataList="allDataList"/>
const state = reactive({
contentValue:'', //选中的年份
allDataList:[2018,2019],// 加这个属性呢是实现年份下方加黄色小圆点
})
//组件里选中的年份传过来的事件
const handlerInput = (value) =>{
console.log(value)
state.contentValue = value
}