Vue2?elementUI年份區(qū)間選擇組件使用方法
一、顯現(xiàn)效果

二、組件封裝yearPicker.vue
<template>
<div class="yearPicker" ref="yearPicker" :style="{ width: width + 'px' }">
<div class="_inner labelText" :style="{ width: labelWidth + 'px' }">{{ labelText }}</div>
<input class="_inner" ref="inputLeft" v-model.number="startShowYear" @focus="onFocus" type="text" @click="clickInput"
name="yearInput" @input="checkStartInput($event)" placeholder="選擇年份" />
<span>{{ sp }}</span>
<input class="_inner" ref="inputRight" v-model.number="endShowYear" @focus="onFocus" type="text" @click="clickInput"
name="yearInput" @input="checkEndInput($event)" placeholder="選擇年份" />
<div class="_inner floatPanel" v-if="showPanel">
<div class="_inner leftPanel">
<div class="_inner panelHead">
<i class="_inner el-icon-d-arrow-left" @click="onClickLeft"></i>
{{ leftYearList[0] + "-" + leftYearList[9] }}
</div>
<div class="_inner panelContent">
<div v-for="item in leftYearList" :class="{
disabled: checkValidYear(item) != 0,
oneSelected: item === startYear && oneSelected,
startSelected: item === startYear,
endSelected: item === endYear,
_inner: true,
betweenSelected: item > startYear && item < endYear
}" :key="item">
<a :class="{
cell: true,
_inner: true,
selected: item === startYear || item === endYear
}" @click="onClickItem(item)" @mouseover="onHoverItem(item)">
{{ item }}
</a>
</div>
</div>
</div>
<div class="_inner rightPanel">
<div class="_inner panelHead">
<i class="_inner el-icon-d-arrow-right" @click="onClickRight"></i>
{{ rightYearList[0] + "-" + rightYearList[9] }}
</div>
<div class="_inner panelContent">
<div :class="{
disabled: checkValidYear(item) != 0,
startSelected: item === startYear,
endSelected: item === endYear,
betweenSelected: item > startYear && item < endYear
}" v-for="item in rightYearList" :key="item">
<a :class="{
cell: true,
_inner: true,
selected: item === endYear || item === startYear
}" @click="onClickItem(item)" @mouseover="onHoverItem(item)">
{{ item }}
</a>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
const SELECT_STATE = {
unselect: 0, //未選擇
selecting: 1, //選中一個(gè)
selected: 2, //全部選中
};
export default {
name: "YearPicker",
computed: {
oneSelected () {
return (
this.curState === SELECT_STATE.selecting && (this.startYear === this.endYear || this.endYear == null)
);
},
startDate () {
return this.startYear;
},
leftYearList () {
return this.yearList.slice(0, 10);
},
rightYearList () {
return this.yearList.slice(10, 20);
}
},
props: {
width: {
default: 200,
},
labelWidth: {
default: 80,
},
labelText: {
default: "時(shí)間標(biāo)簽",
},
sp: {
default: "至",
},
initYear: {
default: null,
},
},
data () {
return {
startShowYear: null,//輸入框 開始年份
endShowYear: null,//輸入框 結(jié)束年份
yearList: [], //選擇框里可選擇的年份
showPanel: false, //選擇框是否顯示
startYear: null, //選擇框選中的開始年份
endYear: null, //選擇框選中的結(jié)束年份
curYear: 0,
curSelectedYear: 0,
curState: SELECT_STATE.unselect,
};
},
methods: {
// 重置時(shí)間范圍
onReset () {
this.startYear = null;
this.endYear = null;
this.startShowYear = null;
this.endShowYear = null;
this.$emit("updateTimeRange", {
startYear: null,
endYear: null,
});
},
// 檢查年份是否在可選區(qū)間內(nèi) 是否禁用
checkValidYear (iYear) {
if (this.initYear) {
if (iYear > this.initYear.endYear) {
return 1
} else if (iYear < this.initYear.startYear) {
return -1
}
}
return 0
},
// 開始年份 輸入框校驗(yàn) 并將選擇框?qū)?yīng)開始年份選中
checkStartInput (event) {
if (isNaN(this.startShowYear)) {
this.startShowYear = this.startYear;
} else {
this.startYear = this.startShowYear * 1;
}
},
// 結(jié)束年份 輸入框校驗(yàn) 并將選擇框?qū)?yīng)結(jié)束年份選中
checkEndInput () {
if (isNaN(this.endShowYear)) {
this.endShowYear = this.endYear;
} else {
this.endYear = this.endShowYear * 1;
}
},
// 選擇框 鼠標(biāo)懸停事件 選中年份范圍
onHoverItem (iYear) {
if (this.checkValidYear(iYear) != 0) {
return;
}
if (this.curState === SELECT_STATE.selecting) {
let tmpStart = this.curSelectedYear;
this.endYear = Math.max(tmpStart, iYear);
this.startYear = Math.min(tmpStart, iYear);
}
},
// 選擇框 點(diǎn)擊事件 選中年份范圍
onClickItem (iYear) {
if (this.checkValidYear(iYear) != 0) {
// 點(diǎn)擊禁用年份 直接返回
return;
}
if (this.curState === SELECT_STATE.unselect || this.curState === SELECT_STATE.selected) {
// 點(diǎn)擊未選擇或全部選中狀態(tài) 開始年份直接選中當(dāng)前年份
this.startYear = iYear;
this.curSelectedYear = iYear;
this.endYear = null;
this.curState = SELECT_STATE.selecting;
} else if (this.curState === SELECT_STATE.selecting) {
// 處于選中一個(gè),然后再點(diǎn)擊
// 如果 開始年份和結(jié)束年份是一樣 但 結(jié)束年份值為空 則 結(jié)束年份 == 開始年份
if(this.startYear && !this.endYear){
this.endYear = this.startYear;
}
this.endShowYear = this.endYear;
this.startShowYear = this.startYear;
this.curState = SELECT_STATE.selected;
this.$emit("updateTimeRange", {
startYear: this.startYear,
endYear: this.endYear,
});
setTimeout(() => {
//為動畫留的時(shí)間,可優(yōu)化
this.showPanel = false;
}, 300);
}
},
//使 input 獲取焦點(diǎn)
onFocus () {
this.$nextTick(() => {
this.showPanel = true;
if(this.startShowYear && this.endShowYear){
// 點(diǎn)擊選擇框 已選擇年份范圍 則將選擇框?qū)?yīng)年份選中
this.endYear = this.endShowYear;
this.startYear = this.startShowYear;
this.curState = SELECT_STATE.selected;
}
});
},
// 點(diǎn)擊 input 阻止事件冒泡
clickInput (e) {
e.stopPropagation();
return false;
},
// 點(diǎn)擊空白區(qū)域關(guān)閉選擇框
closePanel (e) {
if (!this.showPanel) {
return;
}
if (typeof e.target.className !== "string" || e.target.className === "") {
this.$nextTick(() => {
this.changeYear();
this.showPanel = false;
});
return;
}
if (
e.target.className.indexOf("_inner") === -1 ||
(e.target.name === "yearInput" &&
e.target !== this.$refs.inputLeft &&
e.target !== this.$refs.inputRight)
) {
this.$nextTick(() => {
this.changeYear();
this.showPanel = false;
});
}
e.stopPropagation();
return false;
},
// 點(diǎn)擊空白區(qū)域關(guān)閉選擇框 時(shí)間檢驗(yàn)回顯
changeYear () {
if (!this.startYear || !this.endYear) {
return;
}
if (this.startYear > this.endYear) {
let tmp = this.endYear;
this.endYear = this.startYear;
this.startYear = tmp;
}
if (this.initYear) {
this.startYear = Math.max(this.startYear, this.initYear.startYear)
this.endYear = Math.min(this.endYear, this.initYear.endYear)
}
this.startShowYear = this.startYear;
this.endShowYear = this.endYear;
if (this.startYear && this.endYear) {
this.$emit("updateTimeRange", {
startYear: this.startYear,
endYear: this.endYear + ""
});
} else {
console.warn("WARN:年份不合法", this.startYear, this.endYear);
}
},
// 點(diǎn)擊左箭頭 切換到上一個(gè)十年
onClickLeft () {
this.curYear = this.curYear * 1 - 10;
this.updateYearList();
},
// 點(diǎn)擊右箭頭 切換到下一個(gè)十年
onClickRight () {
this.curYear = this.curYear * 1 + 10;
this.updateYearList();
},
// 更新年份列表
updateYearList () {
let iStart = Math.floor(this.curYear / 10) * 10 - 10;
iStart = iStart < 0 ? 0 : iStart;
this.yearList = [];
for (let index = 0; index < 20; index++) {
this.yearList.push(iStart + index);
}
},
//------------------對外接口------------------------
// //直接傳時(shí)間戳
// setYear(startYearStamp, endYearStamp) {
// if (!isNaN(startYearStamp) && !isNaN(endYearStamp)) {
// let startYear = moment(startYearStamp).format("yyyy");
// let endYear = moment(endYearStamp).format("yyyy");
// this.startYear = startYear * 1;
// this.endYear = endYear * 1;
// this.endShowYear = endYear * 1;
// this.startShowYear = startYear * 1;
// }
// },
},
created () {
this.curYear = new Date().getFullYear();
this.updateYearList();
},
beforeUnmount () {
// 組件銷毀時(shí)移除事件監(jiān)聽
// 點(diǎn)擊空白區(qū)域關(guān)閉選擇框
document.removeEventListener("click", this.closePanel.bind(this));
},
mounted () {
// 組件掛載時(shí)添加事件監(jiān)聽
// 點(diǎn)擊空白區(qū)域關(guān)閉選擇框
document.addEventListener("click", this.closePanel.bind(this));
},
};
</script>
<style lang="scss" scoped>
.yearPicker {
font-size: 14px;
display: flex;
position: relative;
transition: all 0.3s;
input {
text-align: center;
}
input:first-child {
text-align: right;
}
background-color: #fff;
.labelText {
text-align: center;
}
span {
padding: 0 8px;
height: 38px;
line-height: 38px;
}
border: 1px solid #eff1f3;
height: 40px;
line-height: 40px;
border-radius: 4px;
padding: 0 28px 0 8px;
box-sizing: border-box;
.floatPanel {
>div {
width: 50%;
}
padding: 0 16px;
position: absolute;
display: flex;
background-color: #fff;
z-index: 2000;
border-radius: 4px;
width: 650px;
height: 250px;
top: 40px;
left: -10px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
.panelContent {
display: flex;
flex-wrap: wrap;
width: 100%;
height: calc(100% - 70px);
.disabled {
color: #ccc;
}
.oneSelected {
border-top-right-radius: 24px;
border-bottom-right-radius: 24px;
}
.startSelected {
background-color: #f6f6f7;
border-top-left-radius: 24px;
border-bottom-left-radius: 24px;
}
.endSelected {
background-color: #f6f6f7;
border-top-right-radius: 24px;
border-bottom-right-radius: 24px;
}
.betweenSelected {
background-color: #f6f6f7;
}
>div {
width: 75px;
height: 48px;
line-height: 48px;
margin: 3px 0;
// border-radius: 24px;
text-align: center;
a {
display: inline-block;
width: 60px;
height: 36px;
cursor: pointer;
line-height: 36px;
border-radius: 18px;
}
.selected {
background-color: #3e77fc;
color: #fff;
}
}
}
.panelHead {
position: relative;
height: 46px;
line-height: 46px;
text-align: center;
i {
position: absolute;
cursor: pointer;
&:hover {
color: #3e77fc;
}
}
}
.rightPanel {
padding-left: 8px;
}
.leftPanel .panelHead i {
left: 20px;
top: 15px;
}
.rightPanel .panelHead i {
right: 20px;
top: 15px;
}
}
.floatPanel::before {
content: "";
height: 100%;
position: absolute;
left: 50%;
width: 1px;
border-left: 1px solid #e4e4e4;
}
}
input {
width: 60px;
border: none;
height: 40px;
line-height: 40px;
box-sizing: border-box;
background-color: transparent;
}
input:focus {
outline: none;
background-color: transparent;
}
.yearPicker:hover {
border-color: #3e77fc;
}
.dateIcon {
position: absolute;
right: 16px;
top: 9px;
color: #adb2bc;
}
</style>三、組件使用
<template>
<div class="moneyType">
<div class="moneyType_con">
<el-form :inline="true" :model="formInline" class="demo-form-inline">
<el-form-item label="年度">
<YearPicker ref="yearPicker" labelText="" :label-width="0" :initYear="initYear" @updateTimeRange="updateStatisticYear"></YearPicker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="getData(1)">查詢</el-button>
<el-button type="success" icon="el-icon-refresh" @click="onReset(1)">重置</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script>
import YearPicker from "../components/yearPicker.vue";
export default {
components: {
YearPicker
},
data () {
return {
initYear: {
startYear: 1945,
endYear: new Date().getFullYear()
},//年份區(qū)間選擇框初始時(shí)間
formInline: {
nd: '',
nds: '',
},
};
},
mounted () {
},
methods: {
// 更新時(shí)間范圍
updateStatisticYear({startYear, endYear}){
this.formInline.nd = startYear
this.formInline.nds = endYear
},
// 查詢
getData () {
},
// 重置
onReset () {
this.formInline = {
nd: '',
nds: '',
}
this.$refs.yearPicker.onReset()
this.getData();
},
},
};
</script>四、實(shí)現(xiàn)功能
1、可選年份區(qū)間(區(qū)間外禁止點(diǎn)擊和選擇,同時(shí)校正輸入)。
2、實(shí)現(xiàn)選擇開始年和結(jié)束年一樣,如2024-2024。
3、實(shí)現(xiàn)彈框顯示時(shí)回顯當(dāng)前選擇的開始年和結(jié)束年。
到此這篇關(guān)于Vue2 elementUI年份區(qū)間選擇組件使用的文章就介紹到這了,更多相關(guān)Vue2 elementUI年份區(qū)間選擇組件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue cli3中eslint報(bào)錯(cuò)no-undef和eslint規(guī)則配置方式
這篇文章主要介紹了vue cli3中eslint報(bào)錯(cuò)no-undef和eslint規(guī)則配置方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08
elementui源碼學(xué)習(xí)仿寫el-link示例詳解
這篇文章主要為大家介紹了elementui源碼學(xué)習(xí)仿寫el-link示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
Vue Cli3 創(chuàng)建項(xiàng)目的方法步驟
Vue CLI是一個(gè)用于快速Vue.js開發(fā)的完整系統(tǒng)。這篇文章主要介紹了Vue Cli3 創(chuàng)建項(xiàng)目的方法步驟,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2018-10-10
解決vue keep-alive 數(shù)據(jù)更新的問題
今天小編就為大家分享一篇解決vue keep-alive 數(shù)據(jù)更新的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09
el-form組件使用resetFields重置失效的問題解決
用el-form寫了包含三個(gè)字段的表單,使用resetFields方法進(jìn)行重置,發(fā)現(xiàn)點(diǎn)擊重置或要清空校驗(yàn)時(shí)是失效的,所以本文給大家介紹了el-form組件使用resetFields重置失效的問題解決,需要的朋友可以參考下2023-12-12
Vue中使用video.js實(shí)現(xiàn)截圖和視頻錄制與下載
這篇文章主要為大家詳細(xì)介紹了Vue中如何使用video.js實(shí)現(xiàn)截圖和視頻錄制與下載,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03
vue實(shí)現(xiàn)點(diǎn)擊翻轉(zhuǎn)效果
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)點(diǎn)擊翻轉(zhuǎn)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07
Vuex模塊化實(shí)現(xiàn)待辦事項(xiàng)的狀態(tài)管理
本文主要介紹了Vuex模塊化實(shí)現(xiàn)待辦事項(xiàng)的狀態(tài)管理的相關(guān)知識,具有很好的參考價(jià)值,下面跟著小編一起來看下吧2017-03-03

