基于vue2+elementUI年份范围选择器

基于vue2+elementUI实现年份范围选择器,支持时间跨度设置。代码如下:

<template><el-popoverref="popover"placement="bottom"v-model="showPanel"popper-class="custom_year_range"trigger="manual"@hide="onHide()"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,disabledSelect: compareNum && (compareNum - maxRange > item || compareNum + maxRange < item)}"v-for="item in leftYearList":key="item"><a:class="{cell: true,_inner: true,selected: item === startYear || item === endYear,isDisabled: compareNum && (compareNum - maxRange > item || compareNum + maxRange < item)}"@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,disabledSelect: compareNum && (compareNum - maxRange > item || compareNum + maxRange < item)}"v-for="item in rightYearList":key="item"><a:class="{cell: true,_inner: true,isDisabled:compareNum && (compareNum - maxRange > item || compareNum + maxRange < item),selected: item === endYear || item === startYear}"@click="onClickItem(item)"@mouseover="onHoverItem(item)">{{ item }}</a></div></div></div></div><div slot="reference"><divref="yearPicker"@mouseenter="startShowYear && endShowYear && (showClearIcon = true)"@mouseleave="showClearIcon = false"class="yearPicker el-date-editor el-range-editor el-input__inner el-date-editor--daterange el-range-editor--small"><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')" /><iv-if="showClearIcon && clearable"class="el-icon-circle-close clearIcon"@click.prevent="onClickClear()"></i></div></div></el-popover>
</template><script>
import moment from 'moment';
import {clickoutside} from '../directives/directives.m.js';
const SELECT_STATE = {unselect: 0,selecting: 1,selected: 2
};
export default {name: 'yearPicker',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: {default: null},startPlaceholder: {type: String,default: '开始年份'},endPlaceholder: {type: String,default: '结束年份'},clearable: {type: Boolean,default: false},// 是否需要限制时间跨度 配合maxRange使用hasDisabled: {type: Boolean,default: false},// 时间跨度 必须与hasDisabled配合使用才生效maxRange: {type: Number,default: 0}},data() {return {itemBg: {},startShowYear: null,endShowYear: null,yearList: [],showPanel: false,startYear: null,endYear: null,curYear: 0,curSelectedYear: 0,curState: SELECT_STATE.unselect,showClearIcon: false,compareNum: 0};},methods: {handleInput(type) {switch (type) {case 'start':if (isNaN(this.startShowYear)) {this.startShowYear = this.startYear;return;}this.startYear = this.startShowYear * 1;break;case 'end':if (isNaN(this.endShowYear)) {this.endShowYear = this.endYear;return;}this.endYear = this.endShowYear * 1;break;}[this.startYear, this.endYear] = [this.endYear, this.startYear];this.startShowYear = this.startYear;this.endShowYear = this.endYear;},onHoverItem(iYear) {if (this.hasDisabled) {if (iYear > this.compareNum + this.maxRange || iYear < this.compareNum - this.maxRange) {return;}}if (this.curState === SELECT_STATE.selecting) {const tmpStart = this.curSelectedYear;this.endYear = Math.max(tmpStart, iYear);this.startYear = Math.min(tmpStart, iYear);}},async onClickItem(selectYear) {if (this.hasDisabled) {if (this.compareNum &&(selectYear > this.compareNum + this.maxRange || selectYear < this.compareNum - this.maxRange)) {return;}}if (this.curState === SELECT_STATE.unselect || this.curState === SELECT_STATE.selected) {this.startYear = selectYear;this.curSelectedYear = selectYear;this.endYear = null;this.curState = SELECT_STATE.selecting;if (this.hasDisabled) {this.compareNum = selectYear;}} else if (this.curState === SELECT_STATE.selecting) {this.endShowYear = this.endYear || this.startYear;this.startShowYear = this.startYear;this.curState = SELECT_STATE.selected;await this.$nextTick();this.showPanel = false;this.$emit('picker-change', [this.startShowYear, this.endShowYear]);// this?.$parent?.$parent?.$parent?.$parent?.$parent.clearValidate?.();}},async onFocus() {if (this.value?.length) {const [first, end] = this.value || [];this.startYear = first || null;this.endYear = end || null;this.curState = SELECT_STATE.selected;this.startShowYear = first;this.endShowYear = end;this.updateYearList();this.compareNum = 0;}await this.$nextTick();this.showPanel = true;},updateYearList() {const startYear = ~~(this.curYear / 10) * 10 - 10;this.yearList = [];for (let index = 0; index < 20; index++) {this.yearList.push(startYear + index);}},onClickLeft() {this.curYear = this.curYear * 1 - 10;this.updateYearList();},onClickRight() {this.curYear = this.curYear * 1 + 10;this.updateYearList();},onClickClear() {this.startYear = null;this.endYear = null;this.startShowYear = null;this.endShowYear = null;this.curState = SELECT_STATE.selected;this.curYear = moment().format('yyyy');this.updateYearList();this.$emit('picker-change', []);},onHide() {this.startYear = null;this.endYear = null;this.curState = SELECT_STATE.selected;this.curYear = moment().format('yyyy');this.updateYearList();}},watch: {value: {handler(val) {if (val?.length === 0) {return;}const [first, end] = val || [];this.startShowYear = first;this.endShowYear = end;},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() {const [startYear, endYear] = this.value || [];if (startYear) {this.startYear = Number(startYear);this.endYear = Number(endYear);this.curState = SELECT_STATE.selected;this.curYear = startYear;} else {this.curYear = moment().format('yyyy');}this.updateYearList();},mounted() {window.Vue = this;}
};
</script>
<style lang="scss">
.custom_year_range {.floatPanel {> div {width: 50%;}padding: 0 16px;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;}.disabledSelect {background-color: #f5f5f5;cursor: not-allowed;}> div {width: 75px;height: 48px;line-height: 48px;margin: 3px 0;text-align: center;a {display: inline-block;cursor: pointer;width: 60px;height: 36px;line-height: 36px;border-radius: 18px;&:hover {// color: #4088fe;text-decoration: none;cursor: pointer;}}a.isDisabled:hover {color: #4088fe;text-decoration: none;cursor: not-allowed !important;}.selected {background-color: #4088fe;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: #4088fe;}}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;}.el-range-separator {min-width: 24px;border: 1px solid #e4e4e4;}
}
</style>
<style lang="scss" scoped>
.yearPicker {width: 290px;.range_input {appearance: none;border: none;outline: 0;padding: 0;width: 40%;color: #606266;line-height: 1;height: 100%;margin: 0;text-align: center;display: inline-block;}.clearIcon {height: 32px;line-height: 32px;position: absolute;right: 8px;color: #c0c4cc;transition: all 0.3;}.el-range-separator {min-width: 24px;}
}

 

// 自定义指令
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__ = documentHandler;document.addEventListener('click', documentHandler);},unbind(el, binding) {// 解除事件监听document.removeEventListener('click', el.__vueClickOutside__);delete el.__vueClickOutside__;}
};

因为项目工期比较赶,功能可能会存在缺陷,码友们若有发现,请留言告知,感谢!

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

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

相关文章

【C/C++笔试练习】sort排序、STL容器、vector的特性、一级容器、迭代器失效、异常捕获、动态转换、统计每个月兔子的总数、字符串通配符

文章目录 C/C笔试练习选择部分&#xff08;1&#xff09;sort是不稳定排序&#xff08;2&#xff09;存放即有序的STL容器&#xff08;3&#xff09;连续储存的STL容器&#xff08;4&#xff09;vector的特性&#xff08;5&#xff09;一级容器&#xff08;6&#xff09;unorde…

PLC-IoT 网关开发札记(1):存档和分发 Android App

开篇记 PLC-IoT 网关是作者开发的产品&#xff0c;根据客户需求&#xff0c;立项开发手机 App&#xff0c;为用户提供一种方便、直观、友好的设备操控方式。网关运行的是嵌入式 Linux 操作系统&#xff0c;计划通过某一种通信协议&#xff08;例如 HTTP&#xff0c;MQTT或者 T…

大数定律中心极限定理

1.切比雪夫不等式 切比雪夫不等式可以对随机变量偏离期望值的概率做出估计&#xff0c;这是大数定律的推理基础。以下介绍一个对切比雪夫不等式的直观证明。 1.1 示性函数 对于随机事件A&#xff0c;我们引入一个示性函数 I A { 1 , A发生 0 , A不发生 I_A\begin{cases} 1&…

Chrome浏览器进程工作原理和机制

Chrome浏览器进程工作原理和机制 Chrome架构&#xff1a;一个页面四个进程进程和线程单进程浏览器多进程浏览器多进程浏览器解决的问题Chrome的进程模式 TCP协议&#xff1a;如何保证页面文件被完整送达浏览器IP&#xff1a;把数据包送达目的主机UDP&#xff1a;把数据包送达应…

vivado CDC约束-约束总线偏移

CDC限制 关于CDC约束 时钟域交叉&#xff08;CDC&#xff09;约束适用于具有不同启动和捕获时钟。根据发布和捕获时钟关系以及在CDC路径上设置的定时异常。例如同步时钟之间但被错误路径约束覆盖的CDC路径不定时&#xff0c;并且因此被视为异步CDN。异步CDC路径可以是安全的&…

vue 导出 HTML 结构为 Word 文档(.docx)-支持表格、css样式、图片

在 Web 开发中&#xff0c;有时我们希望用户能够将网页上的 HTML 内容保存为 Word 文档&#xff0c;以便更方便地分享和打印。本文将介绍如何使用 html-docx-js 和 file-saver 这两个 JavaScript 库&#xff0c;实现将 HTML 结构导出为 Word 文档的功能。 工具简介 1. html-d…

lv13 内核模块参数和依赖

1 模块传参 1.1 模块参数设置 将指定的全局变量设置成模块参数 module_param(name,type,perm);//将指定的全局变量设置成模块参数 /* name:全局变量名 type&#xff1a;使用符号 实际类型 传参方式bool bool insmod xxx.ko 变量名0 …

进阶学习——Linux系统磁盘管理与文件系统

目录 一、磁盘 1.认识磁盘 2.分区 2.1MBR&#xff08;Master Boot Record&#xff09;——主引导记录 2.2GPT分区 2.3磁盘分区结构 3.文件系统 3.1文件系统组成 3.1.1XFS ext4 3.1.2swap 3.1.3FAT16、FAT32 3.1.4NTFS&#xff08;xfs&#xff09; 3.1.5EXT4 3…

[Angular] 笔记 9:list/detail 页面以及@Output

1. Output input 好比重力&#xff0c;向下传递数据&#xff0c;list 传给 detail&#xff0c;smart 组件传给 dumb 组件&#xff0c;父组件传给子组件。input 顾名思义&#xff0c;输入数据给组件。 output 与之相反&#xff0c;好比火箭&#xff0c;向上传递数据或事件。ou…

vue3 v-model语法糖

vue2 中父子组件数据同步 父→子 子→父 如何实现&#xff1f; v-model“count” 或者 xxx.sync“msg” v-model 语法糖 完整写法 :value“count” 和 input“count$event” xxx.sync 语法糖 完整写法 :xxx“msg” 和 update:xxx“msg$event” 现在&#xff1a;一个 v-mo…

云计算IaaS、PaaS和SaaS之

提供的服务来比较如下两图 示例图 示例图

整数规划-割平面法

整数规划-割平面法 割平面法思想Gomorys割平面法原理实例 谨以此博客作为学习期间的记录。 割平面法思想 在之前&#xff0c;梳理了分支定界法的流程:分支定界法 除了分支定界法&#xff0c;割平面法也是求解整数规划的另一个利器。 我们已经知道&#xff0c;线性规划的可行域…

vscode软件安装步骤

目录 一、下载软件安装包 二、运行安装包后 一、下载软件安装包 打开vscode官方网址&#xff0c;找到下载界面 链接如下&#xff1a;Download Visual Studio Code - Mac, Linux, Windows 我是windows电脑&#xff0c;各位小伙伴自己选择合适的版本&#xff0c;点击下载按钮…

从数据洞察到市场变革:我们的 Web3 愿景

shellyfootprint.network 2023 年&#xff0c;我们见证了加密市场的潮起潮落&#xff0c;在这个不断变化的世界中&#xff0c;我们始终坚守着创新的信念&#xff0c;致力于打造强大的数据分析工具。 我们深知&#xff0c;开拓创新是推动 Web3 发展的关键。因此&#xff0c;我…

基于虚拟机ubuntu的linux和shell脚本的学习,以及SSH远程登陆实战

简介 特点 是一款操作系统,跟windows,macos一样,有下面的特点 简单和高效,一切皆文件,所有配置都通过修改文件解决,不需要繁琐的权限和设置 权限高,把所有细节都交给用户,可完全自定义 安全,所有程序只有自己执行才会启动 分类 1、debian系主要有Debian&#xff0c;Ubun…

ESP32入门六(读取引脚的模拟信号[3]:信号出现误差的原因[硬件篇])

在之前的文章中&#xff0c;我们介绍了ESP32在读取模拟信号时出现的误差的软件方面原因&#xff0c;在这一篇中&#xff0c;将会介绍并测试由于硬件或其它方面导致数据出现误差的原因。 一、厂商原因 首先&#xff0c;我们需要知道&#xff0c;在每块EPS32中&#xff0c;在出…

海凌科HLK-V2语音识别模块更新词条

简介 HLK-V20 是海凌科的离线语音识别模块, 中英文不同时支持, 只支持中文/英文, 具体识别看每次的SDK更新设置;资料下载 可以在微信公众包搜索海凌科或HI-LINK, 下载资料 感知模块->HLK-V20 模块限制 中英文被限制, 需要根据你在官网设置的SDK信息进行确定;可以仅设置3…

goframe v2 模板引擎的用法

这里用的goframe v2框架 提醒&#xff1a;下面的import 引入的控制器和api&#xff0c;根据自己实际项目路径 main函数 import ("context""github.com/gogf/gf/v2/net/ghttp""github.com/gzdzh/dzhgo/modules/dzhCms/controller/web""gith…

mysql_存储过程

举例子 createdefiner root% procedure insert_batch_test(IN START int(10), IN max_num int(10)) BEGINDECLAREi INT DEFAULT 0;SET autocommit 0;REPEATSET i i 1;INSERT INTO test (std, score)VALUES (CEILING(RAND() * 10 100), CEILING(RAND() * 50 50));UNTIL i …

STM32移植LVGL图形库

1、问题1&#xff1a;中文字符keil编译错误 解决方法&#xff1a;在KEIL中Options for Target Flash -> C/C -> Misc Controls添加“--localeenglish”。 问题2&#xff1a;LVGL中显示中文字符 使用 LVGL 官方的在线字体转换工具&#xff1a; Online font converter -…