elementUI 年份范围选择器实现

elementUI 不支持年份范围的选择器,依照下面的文章进行修改和完善 el-year-picker

element日期选择范围、选择年份范围_elemet 两个日期 选择的年份范围必须在三年之内-CSDN博客


 el-year-picker 组件:

依赖包:moment
属性:
  • sp:默认 ‘至’
  • value:默认 [ ] 
  • size:默认 large,支持 small、mini
  • clearable:默认 true
  • startPlaceholder:默认 开始年份
  • endPlaceholder:默认 结束年份

事件:
  • input:参数 value[ ]

 效果图

代码

index.vue 
<template><el-popoverref="popover"placement="bottom"v-model="showPanel"popper-class="custom_year_range"trigger="manual"v-clickoutside="() => { showPanel = false }"><div class="_inner floatPanel"><div class="_inner leftPanel"><div class="_inner panelHead"><i class="_inner el-icon-d-arrow-left" @click="onClickLeft"></i><span>{{ leftYearList[0] + '年 ' + '- ' + leftYearList[9] + '年' }}</span></div><div class="_inner panelContent"><div:class="{oneSelected: item === startYear && oneSelected,startSelected: item === startYear,endSelected: item === endYear,betweenSelected: item > startYear && item < endYear,}"v-for="item in leftYearList":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><span>{{ rightYearList[0] + '年 ' + '- ' + rightYearList[9] + '年' }}</span></div><div class="_inner panelContent"><div:class="{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 slot="reference"><divref="yearPicker"style="width: 100%"class="el-date-editor el-range-editor el-input__inner el-date-editor--daterange yearPicker":class="['el-range-editor--' + size, showPanel ? 'is-active' : '', startShowYear ? 'is-val' : '']"@mouseover="handleHover(true)"@mouseleave="handleHover(false)"><i class="el-input__icon el-range__icon el-icon-date"></i><inputclass="_inner range_input"ref="inputLeft"type="text"name="yearInput":placeholder="startPlaceholder"v-model="startShowYear"@focus="onFocus"@keyup="handleInput('start')"/><span class="el-range-separator">{{ sp }}</span><inputclass="_inner range_input"ref="inputRight"type="text"name="yearInput":placeholder="endPlaceholder"v-model="endShowYear"@focus="onFocus"@keyup="handleInput('end')"/><iclass="el-input__icon el-range__close-icon":class="[startShowYear && isHover && clearable ? 'el-icon-circle-close' : '']"@click="onClear"></i></div></div></el-popover>
</template><script>
import moment from 'moment'
import { clickoutside, SELECT_STATE } from './utils.js'
export default {name: 'ElYearPicker',directives: { clickoutside },computed: {oneSelected () {return this.curState === SELECT_STATE.selecting && (this.startYear === this.endYear || this.endYear == null)},leftYearList () {return this.yearList.slice(0, 10)},rightYearList () {return this.yearList.slice(10, 20)}},props: {sp: {default: '至'},value: {type: Array,default: [],},size: {type: String,default: 'large'},clearable: {type: Boolean,default: true},startPlaceholder: {type: String,default: '开始年份'},endPlaceholder: {type: String,default: '结束年份'}},data () {return {itemBg: {},startShowYear: null,endShowYear: null,yearList: [],showPanel: false,startYear: null,endYear: null,curYear: 0,curSelectedYear: 0,curState: SELECT_STATE.unselect,isHover: false}},methods: {handleInput (type) {switch (type) {case 'start':if (isNaN(this.startShowYear)) {this.startShowYear = this.startYearreturn}this.startYear = this.startShowYear * 1breakcase 'end':if (isNaN(this.endShowYear)) {this.endShowYear = this.endYearreturn}this.endYear = this.endShowYear * 1break}[this.startYear, this.endYear] = [this.endYear, this.startYear]this.startShowYear = this.startYearthis.endShowYear = this.endYear},onHoverItem (iYear) {if (this.curState === SELECT_STATE.selecting) {const tmpStart = this.curSelectedYearthis.endYear = Math.max(tmpStart, iYear)this.startYear = Math.min(tmpStart, iYear)}},async onClickItem (selectYear) {if (this.curState === SELECT_STATE.unselect ||this.curState === SELECT_STATE.selected) {this.startYear = selectYearthis.curSelectedYear = selectYearthis.endYear = nullthis.curState = SELECT_STATE.selecting} else if (this.curState === SELECT_STATE.selecting) {this.endShowYear = this.endYear || this.startYearthis.startShowYear = this.startYearthis.curState = SELECT_STATE.selectedawait this.$nextTick()this.showPanel = falsethis.$parent.$parent.$parent.$parent.$parent.clearValidate()}},async onFocus () {await this.$nextTick()this.showPanel = true},handleHover (flag) {this.isHover = flag},updateYearList () {const startYear = ~~(this.curYear / 10) * 10console.log(startYear, this.curYear, 'this.curYearthis.curYearthis.curYear')this.yearList = []for (let index = 0; index < 20; index++) {this.yearList.push(startYear + index)}},onClickLeft () {this.curYear = this.curYear * 1 - 10this.updateYearList()},onClickRight () {this.curYear = this.curYear * 1 + 10this.updateYearList()},onClear () {if (this.startShowYear && this.isHover && this.clearable) {this.startYear = nullthis.endYear = nullthis.curSelectedYear = 0this.curState = SELECT_STATE.unselectthis.showPanel = false;this.curYear = moment().format('yyyy')this.updateYearList()this.startShowYear = ''this.endShowYear = ''this.$emit('input', [])}}},watch: {value: {handler (val) {if (val.length == 0) {this.startShowYear = ''this.endShowYear = ''} else {const [first, end] = val || []this.startShowYear = val[0]this.endShowYear = val[1]}},immediate: true,deep: true},startShowYear: {handler (val) {this.$emit('input', [val, this.endShowYear || ''])},immediate: true,deep: true},endShowYear: {handler (val) {this.$emit('input', [this.startShowYear || '', val])},immediate: true,deep: true}},created () {console.log('value', this.value)const [startYear, endYear] = this.value || []if (startYear) {this.startYear = Number(startYear)this.endYear = Number(endYear)this.curState = SELECT_STATE.selectedthis.curYear = startYear} else {this.curYear = moment().format('yyyy')}this.updateYearList()},mounted () {window.Vue = this}
}
</script>
<style lang="scss">
.custom_year_range {border-radius: 10px;.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: -50px;.panelContent {display: flex;flex-wrap: wrap;width: 100%;height: calc(100% - 70px);.oneSelected {border-top-right-radius: 24px;border-bottom-right-radius: 24px;}.startSelected {background-color: #f2f6fc;border-top-left-radius: 24px;border-bottom-left-radius: 24px;}.endSelected {background-color: #f2f6fc;border-top-right-radius: 24px;border-bottom-right-radius: 24px;}.betweenSelected {background-color: #f2f6fc;}> 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;&:hover {color: #409eff;}}.selected {background-color: #409eff;color: #fff;&:hover {color: #fff !important;}}}}.panelHead {position: relative;height: 46px;line-height: 46px;text-align: center;display: flex;align-items: center;justify-content: center;span {font-size: 16px;font-weight: 500;padding: 0 5px;line-height: 22px;text-align: center;cursor: pointer;color: #606266;&:hover {color: #409eff;}}i {position: absolute;cursor: pointer;&:hover {color: #3e77fc;}}}.rightPanel {padding-left: 8px;}.leftPanel .panelHead i {left: 20px;}.rightPanel .panelHead i {right: 20px;}}.floatPanel::before {content: '';height: 100%;top: 0;position: absolute;left: 50%;width: 1px;border-left: 1px solid #e4e4e4;}.cell._inner {color: #606266;text-decoration: none;}
}
</style>
<style lang="scss" scoped>
.range_input {appearance: none;border: none;outline: 0;padding: 0;width: 130px;color: #606266;line-height: 1;height: 100%;margin: 0;text-align: center;display: inline-block;
}.yearPicker {.el-icon-circle-close {color: #c0c4cc;&:hover {color: #909399;}}&.is-val {}&.is-active {border-color: #0052d9 !important;}
}input {width: 60px;border: none;height: 32px;line-height: 32px;box-sizing: border-box;background-color: transparent;
}input:focus {outline: none;background-color: transparent;
}
.dateIcon {position: absolute;right: 16px;top: 9px;color: #adb2bc;
}
</style>
utils.js
export const clickoutside = {bind(el, binding, vnode) {function documentHandler(e) {// 这里判断点击的元素是否是本身,是本身,则返回if (el.contains(e.target)) {return false}// 判断指令中是否绑定了函数if (binding && binding.expression) {// 如果绑定了函数 则调用那个函数,此处binding.value就是handleClose方法if (binding.value && binding.value(e)) {binding.value(e)}}}// 给当前元素绑定个私有变量,方便在unbind中可以解除事件监听el.__vueClickOutside__ = documentHandlerdocument.addEventListener('click', documentHandler)},unbind(el, binding) {// 解除事件监听document.removeEventListener('click', el.__vueClickOutside__)delete el.__vueClickOutside__}
}export const SELECT_STATE = {unselect: 0,selecting: 1,selected: 2
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/39004.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LLM-Transformer:经典与前沿方法详解

LLM-Transformer&#xff1a;经典与前沿方法详解 前言 大规模语言模型&#xff08;LLM&#xff09;是当前自然语言处理&#xff08;NLP&#xff09;领域的核心技术&#xff0c;而Transformer架构作为LLM的基础&#xff0c;极大地推动了这一领域的发展。本文将详细介绍LLM-Tra…

轻松拯救手机数据,数据恢复软件推荐这8款!

在现代生活中&#xff0c;手机已成为我们不可或缺的工具&#xff0c;承载着大量重要的个人和工作数据。然而&#xff0c;意外删除、系统崩溃、设备损坏等情况可能导致数据丢失&#xff0c;给我们带来极大的困扰。幸运的是&#xff0c;随着科技的发展&#xff0c;各种手机数据恢…

【C++之unordered_set和unordered_map的介绍与应用】

C学习笔记---024 C之unordered_set和unordered_map的介绍与应用1、unordered_set和unordered_map的简单介绍1.1、unordered_set和unordered_map的基本概念1.2、unordered_set和unordered_map的基本特性 2、unordered_set的基本操作2.1、unordered_set的定义2.2、unordered_set的…

Mysql迁移数据报错:1114 – The table ‘xxxx’is full问题以及迁移mysql

今天用Navicat迁移数据的时候&#xff0c;报了一个错:1114 – The table ‘xxxx’is full 解决方案一:修改mysql的配置 这个问题可能是2种原因: 1.存放数据的磁盘整的已经放满&#xff0c;不能再写入数据&#xff0c;需要优化磁盘的存储大小。2.超过了mysql的临时表大小 和内…

顶顶通语音信箱手机助手拦截方案

在电话自动外呼系统&#xff0c;常见的问题是被叫号码开通了语音信箱&#xff0c;或者运营商自动给开通了小秘书服务&#xff0c;一旦电话打不通&#xff0c;就会先播放一个类似这样的提示音&#xff0c;你拨打的电话已经开启了来电小秘书&#xff0c;请在滴声后留言。还有一个…

【面试题】IPS(入侵防御系统)和IDS(入侵检测系统)的区别

IPS&#xff08;入侵防御系统&#xff09;和IDS&#xff08;入侵检测系统&#xff09;在网络安全领域扮演着不同的角色&#xff0c;它们之间的主要区别可以归纳如下&#xff1a; 功能差异&#xff1a; IPS&#xff1a;这是一种主动防护设备&#xff0c;不仅具备检测攻击的能力&…

优思学院|如何管理库存?让浪费和缺货减至最少?

引言&#xff1a;库存在精益生产中的悖论 在精益生产管理中&#xff0c;库存&#xff08;Inventory&#xff09;一直被视为八大浪费之一&#xff0c;因为它占用了资源、空间&#xff0c;并且可能掩盖流程中的问题。然而&#xff0c;库存并非一无是处&#xff0c;特别是在流程尚…

这几类热销品被Ozon限制销售,ozon还有什么产品好卖?

OZON是俄罗斯最大的B2C电商平台&#xff0c;占据俄罗斯电商市场份额的62%&#xff0c;日均订单量高达37万单&#xff0c;拥有超过1600万的活跃用户。ozon平台对中国卖家招商的产品品类涵盖了多个领域&#xff0c;但近日Ozon官方发布将对这三大类目实行销售限制&#xff0c;一起…

微信小程序渲染层与逻辑层交互原理

1. 网页开发与小程序开发有何不同&#xff1f; 2. 小程序运行环境 3. 页面渲染技术选型 1. 纯客户端技术&#xff1b; 2. 纯Web技术&#xff1b; 3. 用客户端原生技术与Web技术结合的混合技术&#xff08;Hybrid&#xff09;&#xff0c;小程序就是使用的这种技术&#xff1…

MacBook关闭谷歌浏览器双指左右移动(扫动)前进后退功能

这个功能真的很反人类&#xff0c;正常上下滑动页面的时候很容易误操作&#xff0c;尤其是当你在一个页面上做了很多的编辑工作后误触发了此手势&#xff0c;那真叫一个崩溃&#xff01; 其实这应该是 Macbook 触控板提供的一个快捷操作&#xff0c;跟浏览器本身估计没关系&am…

基于大模型构建企业私有智能知识库落地的简单实践

​ 随着人工智能技术的飞速发展&#xff0c;大模型在企业知识管理中的应用日益广泛。下文是作者围绕如何基于大模型技术构建企业私有知识库&#xff0c;以提升企业的知识管理效率和创新能力的一些思考和简单实践。 ​ 本文对企业知识库的落地场景暂不作广泛的展开&#xff0c;…

成都百洲文化传媒有限公司网上开店怎么样?

在电商的浪潮中&#xff0c;每一个品牌都在寻找自己的定位与突破。而成都百洲文化传媒有限公司&#xff0c;正是这场浪潮中的一股强大助力&#xff0c;凭借其专业的电商服务&#xff0c;助力无数品牌实现了飞跃发展。 一、专业铸就品质&#xff0c;服务成就品牌 成都百洲文化传…

Runway:Gen-3 Alpha 文生视频现已开放

Runway 自 6 月 17 号公布 Gen-3 Alpha 快半个月了, 现在终于对所有人开放了&#xff0c;当然前提是你至少订阅了标准版&#xff08;12 美刀/月), 传送门&#xff1a;runwayml.com

中原汉族与北方游牧民族舞蹈文化在这段剧中表现得淋漓尽致,且看!

中原汉族与北方游牧民族舞蹈文化在这段剧中表现得淋漓尽致&#xff0c;且看&#xff01; 《神探狄仁杰》之使团喋血记是一部深入人心的历史侦探剧&#xff0c;不仅以其曲折离奇的案情和狄仁杰的睿智形象吸引观众&#xff0c;更以其对唐代文化的精准再现而备受赞誉。#李秘书讲写…

引力波信号的连续小波变换(Python)

提到引力波&#xff0c;就要提到引力波天文学。引力波天文学是观测天文学的一个新兴分支&#xff0c;主要利用引力波&#xff08;微小时空扭曲&#xff09;观测发出引力辐射的天体系统&#xff0c;比如中子星和黑洞等波源、超新星等事件以及大爆炸后不久的早期宇宙演化过程。 …

Java代码基础算法练习-计算平均身高-2024.07.02

任务描述&#xff1a; n个同学站成一排&#xff0c;求它们的平均身高 解决思路&#xff1a; 输入的学生人数为 for 循环次数&#xff0c;循环中每输入一个值就添加在总数中&#xff0c;循环结束总数除以对应的学生人数得到平均身高 代码示例&#xff1a; package a4_2024_07;…

泽州县和美环保科技有限公司——绿色环保的践行者

在环保产业蓬勃发展的今天&#xff0c;泽州县和美环保科技有限公司以其卓越的技术和强大的实力&#xff0c;成为山西省危废综合处置领域的翘楚。作为雅居乐环保集团的全资子公司&#xff0c;和美环保科技有限公司紧跟集团发展战略&#xff0c;致力于为社会提供全方位的环境服务…

JavaSE多线程线程池

文章目录 1. 多线程入门1.1 多线程相关概念1.2 什么是多线程1.3 多线程的创建方式1.3.1 继承 Thread 的方式1.3.2 实现 Runnable 接口的方式1.3.3 实现 Callable 接口的方式1.3.4 Thread 类中常用方法1.3.5 sleep() 方法 和 wait() 方法区别&#xff1a; 2. 线程安全2.1 线程安…

项目实战--Spring Boot + Minio文件切片上传下载

1.搭建环境 引入项目依赖 <!-- 操作minio的java客户端--> <dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.5.2</version> </dependency> <!-- jwt鉴权相应依赖--> &…

Linux下编程之内存检查

前言 我们在进行编程时&#xff0c;有时不免会无意中写出一些容易导致内存问题&#xff08;可能一时表象上正常&#xff09;的代码&#xff0c;导致的后果肯定是不好的&#xff0c;就像一颗颗“哑弹”&#xff0c;令人心慌。网上推荐的辅助工具很多&#xff0c;此篇文章…