当前位置: 首页 > Web前端 > vue.js

从零开始开发一个日期组件

时间:2023-04-01 02:02:04 vue.js

如图,需要开发一个目标时间组件;功能要点:弹出窗口调出后,必须能够显示外部选择的初始值;弹窗操作后,必须能够向外部回调内部选择的值;交互设置Set:类似密码箱的操作方法,上下滑动选择一个值;点击“取消”,弹窗消失;点击“确定”,将选中的值回调给外部;自动校正对齐方式,使选中的文本恰好垂直居中;修改年或月时,日必须重新设置为1,日期选项需要重新设置,防止日期错误,如2月31日;组件分割:灰色弹窗遮挡区域,点击此处弹窗消失;黄色回调操作,这里触发回调隐藏和确认;蓝色滚动单元,这里实现上下滑动和交互规则1,并将滑动后居中的值回调到外面,反转外面设置的选项;绿色业务区,这里负责处理基础业务:解析外部传入的时间存储在里面,设置滚动单元的可选项(如月份列表,日期列表),交互详情2;1、开发蓝色卷轴单元,首先要确定交互方案。滑动可以用scroll实现,也可以touch+translateY实现;方案1,scroll的优点是流畅,有惯性(ios),缺点是需要考虑节流;定位选中的元素会比较困难。需要手动监听滚动结束事件,获取scrollTop距离,计算居中元素;第二种方案,使用touch+translateY,优点是控制简单,但是触摸后没有惯性(或者手动设置惯性(我没有这个技能),比较麻烦);//【基本交互原理】//_handleTouchStart,_handleTouchMove,_handleTouchEnd函数////_handleTouchStart记录初始位置,供后续参考//_handleTouchMove参考初始位置计算滚动距离,并给视图设置//_handleTouchEnd交互结束后,需要修正滚动距离,防止选中的值与视口错位,第一个选项和最后一个选项用于居中;js交互逻辑name:"scrollPicker",props:{options:{type:Array,default:()=>[]},content:{type:Number,default:0},},data(){返回{remPxScale:16,moveScale:10,activeIndex:null,startY:0,};},因为是用vue开发的,不熟悉的可以先看vue入门教程;remPxScale用于表示压缩比,我用rem作为基本单位;moveScale用于设置滑动缩放,增加滑动速度,即我喜欢用手指滑动一个像素就滚动5个像素;activeIndex是当前选中选项的索引;startY为初始滑动位置,记录在_handleTouchStart中;_handleTouchMove(e){constcurrentY=this._getYPosition(e);constnextPostion=this._calYPosition(currentY-this.startY);this._setYPosition(nextPostion);},上面的代码,滑动手指时,计算滑动距离,计算要滚动的距离,即手指移动n次Pixels,计算滚动单元需要多少translateY,然后将其设置为ref="scroll-container";核心部分是_calYPosition的计算,你可以自己实现,我的实现如下,代码有点硬,你可以一笑置之Can:/***计算translateY的当前位置,单位rem*@paramdeltaYNUmber手指划过多少像素px*@paramappendOrignalboolean是否需要叠加处理位置【已废弃】**@variationdeltaRemnumber手指滑动距离转换单位rem*@variationorignalRemnumber初始转换单位rem*@variationmaxPosition数字,最大滚动距离,即不能滚动到第一个元素的顶部*@variationminPosition数字,最大滚动距离,即不能滚动到最后一个元素下面*/_calYPosition(deltaY,appendOrignal=true){constdeltaRem=deltaY/(this.remPxScale*this.moveScale);让orignalRem=0;if(appendOrignal){try{consttransformStr=this.$refs["scroll-container"].style.transform;constmoveRexg=/translateY\((-?\d*\.?\d*)rem\)$/;orignalRem=transformStr.match(moveRexg)[1]||0;}赶上(错误){orignalRem=0;}}constfinalPostion=Number(deltaRem)+Number(orignalRem);const最大位置=0;constminPosition=-(this.options.length-1)*4;如果(finalPostionmaxPosition){returnmaxPosition;}returnfinalPosition;},最后,在滚动结束时,需要对齐,回调选中的值(即滚动到c位置的值,供下滚动单元使用);_handleTouchEnd(e){constfinalY=this._getYPosition(e);constnextPostion=this._calYPosition(finalY-this.startY);constindex=Math.round(-nextPostion/4);this.scrollToIndex(index);},.../***finalvaluefunction*@paramindexNumber指的是打到哪里,滚动到哪个选项*@paramshouldEmitboolean是否触发外部回调*当是一个内部点击或滚动,需要回调外部以确保安全。比如选择月份后,需要重新设置日期,防止被移除,比如February31*设置为external时,不需要回调到external,因为external已经是正确的值了,而下一个级别的值已经在外部进行了处理;*/scrollToIndex(index,shouldEmit=true){this._setYPosition(-index*4);this.activeIndex=索引;shouldEmit&&this.$emit("pickSelect",this.options[index]);},2.开发绿色业务区绿色区域的初始值设置和回调非常简单,不再赘述。先说说如何链接页面上的各个滚动单元。滚动单元使用如下">

handleSelect('月',任何)">
handleSelect('date',any)">
其中options代表滚动单元的选项,比如月份是1-12等;content代表当前选择的年月日,比如我选择的年份是2020;@pickSelect表示滚动单元内选中的值然后,回调到业务区,比如我选择二月,那么我必须把二月回调到业务区,业务区会重新计算二月的天数,并且强制将日期设置为1;查看handleSelect的实现;handleSelect(type,value){switch(type){case"year":this.year=value;这个月=1;这个.date=1;休息;案例“周一th":this.month=value;this.dates=TimeUtils.createDates(value);this.date=1;break;case"date":this.date=value;break;case"hour":this.hour=value;break;case"minute":this.minute=value;break;}}如上,基本日期的约束都在代码中;最后直接在业务组件中组装年月日,丢给confirm回调就可以了,如果需要显示时分,同样的方法即可;