- 如何实现一个6位数的密码输入框
背景: 因为公司业务调整需要做用户支付这一块 开发者需要在小程序上实现一个简单的6位数密码输入框 [图片] 首先想下如何实现该效果: 1.使用input覆盖在框上面,设置letter-spacing达到数字之间间距的效果,实现时发现在input组件上使用letter-spacing无效果 2.循环六个view模拟的框,光标使用动画模拟,一个隐藏的input,点击view框时触发input的Focus属性弹起键盘,同时模拟的光标展示出来,输入值后,input的value长度发生变化,设置光标位置以及模拟的密码小黑圆点 好了,废话不多数,咱们直接上手。 wxml [代码]<view class='container'> <!-- 模拟输入框 --> <view class='pay-box {{focusType ? "focus-border" : ""}}' bindtap="handleFocus" style='width: 604rpx;height: 98rpx'> <block wx:for="{{boxList}}" wx:key="{{index}}"> <view class='password-box {{index === 0 ? "b-l-n":""}}'> <view wx:if="{{(dataLength === item - 1)&& focusType}}" class="cursor"></view> <view wx:if="{{dataLength >= item}}" class="input-black-dot"></view> </view> </block> </view> <!-- 隐藏input框 --> <input value="{{input_value}}" focus="{{isFocus}}" maxlength="6" type="number" class='hidden-input' bindinput="handleSetData" bindfocus="handleUseFocus" bindblur="handleUseFocus" /> </view> [代码] wxss [代码]/* 第一个格子输入框 */ .container .b-l-n { border-left: none; } .pay-box { margin: 0 auto; display: flex; flex-direction: row; border-left: 1px solid #cfd4d3; } /* 支付密码框聚焦的时候 */ .focus-border { border-color: #0c8; } /* 单个格式样式(聚焦的时候) */ .password-box { flex: 1; border: 1px solid #0c8; margin-right: 10rpx; display: flex; align-items: center; justify-content: center; } /* 模拟光标 */ .cursor { width: 2rpx; height: 36rpx; background-color: #0c8; animation: focus 1.2s infinite; } /* 光标动画 */ @keyframes focus { from { opacity: 1; } to { opacity: 0; } } /* 模拟输入的password的黑点 */ .input-black-dot { width: 20rpx; height: 20rpx; background-color: #000; border-radius: 50%; } /* 输入框 */ .hidden-input { margin-top: 200rpx; position: relative; } [代码] JS [代码]Component({ data: { //输入框聚焦状态 isFocus: false, //输入框聚焦样式 是否自动获取焦点 focusType: true, valueData: '', //输入的值 dataLength: '', boxList: [1, 2, 3, 4, 5, 6] }, // 组件属性 properties: { }, // 组件方法 methods: { // 获得焦点时 handleUseFocus() { this.setData({ focusType: true }) }, // 失去焦点时 handleUseBlur() { this.setData({ focusType: false }) }, // 点击6个框聚焦 handleFocus() { this.setData({ isFocus: true }) }, // 获取输入框的值 handleSetData(e) { // 更新数据 this.setData({ dataLength: e.detail.value.length, valueData: e.detail.value }) // 当输入框的值等于6时(发起支付等...) if (e.detail.value.length === 6) { // 通知用户输入数字达到6位数可以发送接口校验密码是否正确 this.triggerEvent('initData', e.detail.value) } } } }) [代码] 实现方式很简单,有点小问题,还有一些后续准备做的优化点,等完善后上线后再来修改一波。 最后附上代码片段: https://developers.weixin.qq.com/s/8CtRqJmT7W8k
2020-07-06 - canvas draw 不执行的一种情况分享下
从昨天开始 线上 小程序 分享 出现不显示的情况; 然后开始解决,之前很确定是没有出现不显示的情况的; 到现在才发现是 因为 canvas 嵌套在 movable-area 中导致; 在这里分享下, 希望兄弟姐妹少踩坑 movable-area 最好不要放在最外层这里发下我的css解决方法 html [代码] <view class="wrap"> <movable-area class="move-area"> <movable-view direction="all" x="x" y="y" inertia="true" class="icon icon-power" @tap="onTap"></movable-view> </movable-area> <popup show="false"> <canvas style="width:300px;height:400px" canvas-id="share-canvas"/> </popup> </view> [代码] css [代码].wrap{position:relative;} .move-area{position: absolute;width:100%;height:100vh;display:block;top:-100vh;} [代码] 代码仅做参考
2019-05-31 - 记一次故障引发的线程池使用的思考
一、悬案 某日某晚 8 时许,一阵急促的报警电话响彻有赞分销员技术团队的工位,小虎同学,小峰同学纷纷打开监控平台一探究竟。分销员系统某核心应用,接口响应全部超时,dubbo 线程池被全部占满,并堆积了大量待处理任务,整个应用无法响应任何外部请求,处于“夯死”的状态。 [图片] 正当虎峰两位同学焦急的以各种姿势查看应用的各项指标时,5分钟过去了,应用居然自己自动恢复了。看似虚惊一场,但果真如此吗? 二、勘查线索 2.1 QPS “是不是又有商家没有备案就搞活动了啊”,小虎同学如此说道。的确,对于应用突然夯死,大家可能第一时间想到的就是流量突增。流量突增会给应用稳定性带来不小冲击,机器资源的消耗的增加至殆尽,就像我们去自助餐厅胡吃海喝到最后一口水都喝不下,当然也就响应不了新的请求。我们查看了 QPS 的状况。 [图片] 事实让人失望,应用的 QPS 指标并没有出现陡峰,处于一个相对平缓的上下浮动的状态,小虎同学不禁一口叹气,看来不是流量突增导致的. 2.2 GC “是不是 GC 出问题了”,框架组一位资深的同学说道。JVM 在 GC 时,会因为 Stop The World 的出现,导致整个应用产生短暂的停顿时间。如果 JVM 频繁的发生 Stop The World,或者停顿时间较长,会一定程度的影响应用处理请求的能力。但是我们查看了 GC 日志,并没有任何的异常,看来也不是 GC 异常导致的。 [图片] 2.3 慢查 “是不是有慢查导致整个应用拖慢?”,DBA 同学提出了自己的看法。当应用的高 QPS 接口出现慢查时,会导致处理请求的线程池中(dubbo 线程池),大量堆积处理慢查的线程,占用线程池资源,使新的请求线程处于线程池队列末端的等待状态,情况恶劣时,请求得不到及时响应,引发超时。但遗憾的是,出问题的时间段,并未发生慢查。 2.4 TIMEDOUT 问题至此已经扑朔迷离了,但是我们的开发同学并没有放弃。仔细的小峰同学在排查机器日志时,发现了一个异常现象,某个平时不怎么报错的接口,在1秒内被外部调用了 500 多次,此后在那个时间段内,根据 traceid 这 500 多次请求产生了 400 多条错误日志,并且错误日志最长有延后好几分钟的。 [图片] 这是怎么回事呢?这里有两个问题让我们疑惑不解: 1、500 QPS 完全在这个接口承受范围内,压力还不够。 2、为什么产生的错误日志能够被延后好几分钟。 日志中明显的指出,这个 http 请求 Read timed out。http 请求中读超时设置过长的话,最终的效果会和慢查一样,导致线程长时间占用线程池资源(dubbo 线程池),简言之,老的出不去,新的进不来。带着疑问,我们翻到了代码。 [图片] 但是代码中确实是设置了读超时的,那么延后的错误日志是怎么来的呢?我们已经接近真相了吗? 三、破案 我们不免对这个 RestTemplateBuilder 起了疑心,是这个家伙有什么暗藏的设置嘛?机智的小虎同学,针对这个工具类,将线上的情况回放到本地进行了模拟。我们构建了 500 个线程同时使用这个工具类去请求一个 http 接口,这个 http 接口让每个请求都等待 2 秒后再返回,具体的做法很简单就是 Thread.sleep(2000),然后观察每次请求的 response 和 rt。 [图片] 我们发现 response 都是正常返回的(没有触发 Read timed out),rt是规律的5个一组并且有 2 秒的递增。看到这里,大家是不是感觉到了什么?对!这里面有队列!通过继续跟踪代码,我们找到了“元凶”。 [图片] 这个工具类默认使用了队列去发起 http 请求,形成了类似 pool 的方式,并且 pool active size 仅有 5。 现在我们来还原下整个案件的经过: 1、500 个并发的请求同时访问了我们应用的某个接口,将 dubbo 线程池迅速占满(dubbo 线程池大小为 200),这个接口内部逻辑需要访问一个内网的 http 接口 2、由于某些不可抗拒因素(运维同学还在辛苦奋战),这个时间段内这个内网的 http 接口全部返回超时 3、这个接口发起 http 请求时,使用队列形成了类似 pool 的方式,并且 pool active size 仅有 5,所以消耗完 500 个请求大约需要 500/52s=200s,这 200s 内应用本身承担着大约 3000QPS 的请求,会有大约 3000200=600000 个任务会进入 dubbo 线程池队列(如悬案中的日志截图)。PS:整个应用当然就凉凉咯。 4、消耗完这 500 个请求后,应用就开始慢慢恢复(恢复的速率与时间可以根据正常 rt 大致算一算,这里就不作展开了)。 四、思考 到这里,大家心里的一块石头已经落地。但回顾整个案件,无非就是我们工作中或者面试中,经常碰到或被问到的一个问题:“对象池是怎么用的呢?线程池是怎么用的呢?队列又是怎么用的呢?它们的核心参数是怎么设置的呢?”。答案是没有标准答案,核心参数的设置,一定需要根据场景来。拿本案举例,本案涉及两个方面: 4.1 发起 http 请求的队列 这个使用队列形成的 pool 的场景是侧重 IO 的操作,IO 操作的一个特性是需要有较长的等待时间,那我们就可以为了提高吞吐量,而适当的调大 pool active size(反正大家就一起等等咯),这和线程池的的 maximum pool size 有着异曲同工之处。那调大至多少合适呢?可以根据这个接口调用情况,平均 QPS 是多少,峰值 QPS 是多少,rt 是多少等等元素,来调出一个合适的值,这一定是一个过程,而不是一次性决定的。那又有同学会问了,我是一个新接口,我不知道历史数据怎么办呢?对于这种情况,如果条件允许的话,使用压测是一个不错的办法。根据改变压测条件,来调试出一个相对靠谱的值,上线后对其观察,再决定是否需要调整。 4.2 dubbo 线程池 在本案中,对于这个线程池的问题有两个,队列长度与拒绝策略。队列长度的问题显而易见,一个应用的负载能力,是可以通过各种手段衡量出来的。就像我们去餐厅吃饭一样,顾客从上桌到下桌的平均时间(rt)是已知的,餐厅一天存储的食物也是已知的(机器资源)。当餐桌满了的时候,新来的客人需要排队,如果不限制队列的长度,一个餐厅外面排上个几万人,队列末尾的老哥好不容易轮到了他,但他已经饿死了或者餐厅已经没吃的了。这个时候,我们就需要学会拒绝。可以告诉新来的客人,你们今天晚上是排不上的,去别家吧。也可以把那些吃完了,但是赖在餐桌上聊天的客人赶赶走(虽然现实中这么挺不礼貌,但也是一些自助餐限时2小时的原因)。回到本案,如果我们调低了队列的长度,增加了适当的拒绝策略,并且可以把长时间排队的任务移除掉(这么做有一定风险),可以一定程度的提高系统恢复的速度。 最后补一句,我们在使用一些第三方工具包的时候(就算它是 spring 的),需要了解其大致的实现,避免因参数设置不全,带来意外的“收获”。 总结了这么多,小虎和小峰同学,终于心满意足的走向了自助餐厅,开始享用他们的晚餐。
2019-06-04 - 混迹社区后,给微信小程序开发者的一些建议
引言 我几乎每天都逛社区,但是由于水平有限参与的回答并不多。但是在我的长期窥屏之下。发现很多开发者的问题极其相似或者同一类型的问题出现频率非常高。故想总结一点建议,希望可以对自称新手的开发者一些帮助。 正文 写代码时请做好备份,一定要养成良好的代码编写习惯。及时将代码push到git或类似的版本控制平台 在提问题之前,请先阅读微信开发者文档,不要遇到问题就在社区里问,能不能,怎么做诸如此类的 如果真的在文档中没有找到或者解决不了,你也要学会利用搜索引擎,不能用谷歌的话,百度也是可以解决大部分问题的,同时善用搜索引擎你将会受益终生(不夸张)。 如果以上两点还是解决不了,请先搜索一下社区中有没有人提过类似问题。 提问请勿标题党,虽然真的实现了你的目的。比如我每次都会点进去,然后看到的却是一大堆吐槽。比如常见的问题:复制粘贴不能用,广告为什会被封,广告组件审核触发机制,流量主收益之类的。我知道这些让你很不爽,但是我还是觉得既然来社区讨论,大家还是文雅点比较好。 请不要让社区的同学来帮你思考,你有个什么需求,你就去想该怎么做,如果想不到,没有人禁止你参考别人的软件流程。比如,提问:做一个新闻小程序要怎么做之类的,我建议你先去看看头条。 提某些需求建议时,请先考虑合不合理的问题。比如,如何获取微信用户零钱?等诸如此类微信官方不可能也不需要去提供的功能。(这是哪个老板提的需求?和我老板有的一拼) 善待微信官方人员 结语 目前就想到这么多,如果有什么遗漏的,欢迎评论区补充。
2019-05-21