产品让我限制一下输入框字数,结果我搞了3天没搞明白

简介: 作为一名新人er,看到自己的文章列表空空如也总觉得不是那么回事。但是想动手写点什么吧,脑子里实在又憋不出什么料。写一篇正儿八经的技术文章真的是好难好麻烦,尤其是看了首页推荐的大佬文章,更是觉得自己那点东西就别拿出去丢人了。有充分借口的日子总是短暂而且美好。这不,就在不久前的一次组会上,老大们又提起了”写点什么“的事儿,并且一再强调,不需要写出个什么宏文出来,写点什么都行。你看这台阶都给到这了,不下

作为一名新人er,看到自己的文章列表空空如也总觉得不是那么回事。但是想动手写点什么吧,脑子里实在又憋不出什么料。写一篇正儿八经的技术文章真的是好难好麻烦,尤其是看了首页推荐的大佬文章,更是觉得自己那点东西就别拿出去丢人了。有充分借口的日子总是短暂而且美好。这不,就在不久前的一次组会上,老大们又提起了”写点什么“的事儿,并且一再强调,不需要写出个什么宏文出来,写点什么都行。你看这台阶都给到这了,不下也不行了,于是我就只能硬着头皮把之前早已抛之脑后的“写点什么”的事儿重新提上日程。对于所有因我标题党行为不幸点开本链接的同学,我对你们致以深深的歉意。但如果您此时正好想歇歇脑子,那么权当图个乐吧。。。

DISCLAIMER

故事情节纯属虚构,如有雷同纯属BUG

Episode 01

中午刚过,龙哥就朝着我的工位走来了,“勇哥,我来跟你商量个事。能不能把这个用户昵称输入框的字数给限制到10个字符”。因为是临时改需求,龙哥的神情略显惶恐,抻着脖子搓着手难为情的问我,“这个事需要多久?”。我自然是听到了龙哥的发问,但并没有着急回复,一个老成的程序员从来不会一上来就把答案说出口,我决定让子弹再飞一会。于是我头也不转地盯着代码,手上依旧敲个不停。这沉默让本就难堪的龙哥变得更加神形窘迫。时间一秒一秒地流逝,在他颤颤巍巍的嘴唇准备张开的一瞬间,我用不掺杂任何人类感情的声音说道,“改好了”。

不知是不是我的错觉,龙哥的眼睛在他听到我回复的一瞬间闪了一下。仿佛他看到了上帝,至少,是让他十分敬畏的事物。等回神过来,龙哥立马喜笑颜开地说,“有事还是勇哥,大佬就是大佬啊”。作为一个老成的程序员,这点夸耀是绝无可能让我冷若冰霜的面庞有丝毫扰动的,我只是轻轻点了一下头,龙哥便识趣地退下了,嘴里还不忘招呼着,“勇哥,你先忙,有空请你吃饭哈”。

龙哥自然不知道我只是在页面里加了一个maxlength=“10”这么简单,而且他可能也永远也不会知道。这并不仅仅是因为他对我说了不下20遍请我吃饭但却从来没有兑现过一顿,哪怕是一杯早餐豆浆+油条,更重要的是,一个魔术师永远不会把他的戏法告诉观众。长时间地保持面无表情让肌肉略显僵硬,但想到这里我嘴角还是不由得上扬了一下,"You have no idea who are you dealing with, don't you?"

Episode 02

次日一早,龙哥略显气急败坏的向我走来,“勇哥,群里的问题我看了,明明就是复制了20个字,但是粘贴进去就只剩下19个字了!测试说的没问题,肯定是你代码有问题!”。

其实我已经隐约觉得哪里不对了,但作为一个老成的程序员,遭受质疑时必须予以回击,于是我发自灵魂地向龙哥发起了拷问,“我电脑上怎么没事?”

在支走了龙哥之后,我就开始着手定位问题,在排除了包含隐藏字符的问题之后,我立马就想起了JS中字符串表示存在的问题。

我们都知道c语言中并没有专门的字符串类型,而是用一个char sequence来表示字符串,而char其实就是一个int值来表示对应字符的ASCII编码;c++为了支持多语言,通过宽字符类型来支持Unicode字符集;而许多其他的高级语言很多都有专门的字符串类型,为了能够支持多语言,通常都以UCS-2或者UTF-16编码作为内码来表示字符串,这其中就包含了JavaScript。Unicode字符集设计之初,认为2个字节足够存储世界上的众多语言符号了,但事与愿违,现在许多加入Unicode的字符已经位于补充平面上,这意味着2个字节已经无法表示这些字符了。JavaScript语言为了向下兼容,不能直接改变现有API的行为,而是通过新增API的方式来扩充语言本身对Unicode字符集的支持,于是有了ES6字符串中的codePointAt/fromCodePoint等基于“点位”的API。

果不其然,通过跟测试同学沟通,发现数据是从一个歌词网站上copy的,里面有一个异体字“”,这是一个东亚通用汉字,编码位于Unicode的补充平面上。

于是我果断使用Array.from来计算字符串的长度,并且通过监听beforeinput和compositionStart/compositionUpdate/compositionEnd输入事件来实现输入限制,代码虽然增加了一大坨,但问题总算解决了。

作为一个老成的程序员,我肯定不能说自己代码有问题。于是乎在群里回复道,“问题的原因我找到了,是因为测试数据中包含非标准的字符,我现在已经通过修改代码兼容了,以后再也不会有这类问题了。“

几秒之后群里爆发了“勇哥牛逼”的接龙消息。但其中也有一条来自龙哥的消息撤回打破了完美的接龙,我估摸着是龙哥对于所谓“使用了非标准字符”的解释并不满意,所以想进行进一步的逼问,但无奈被大家接龙的阵势给唬住了,只得放弃。当然也可能是“不小心”把“勇哥牛逼”发了成了“勇哥X逼”之后又快速撤回了。无论怎样,事情可以告一段落了,群里又恢复到了往日的宁静。

Episode 03

接下来几天没有什么疑难Bug的日子里,我并没有感到快乐,反倒是一种空虚,一种无敌的空虚。手里机械键盘回弹的力度似乎也比往日疲软了一些。

就在我沉浸在愤恨之中的时候,群里却又突然热闹起来了。我打开群消息一看,除了一堆“笑喷”的表情图之外,就是各种俏皮话。

龙哥:勇哥准备扛起国内保守主义的大旗了!

某B:直男官宣!

某C:对不起‍♂️,之前上厕所站你旁边跟你聊天让你感到不适了,下次注意保持距离

某D:本群即日起禁止发送任何兄贵哲学表情图,违者一律踢出群聊!

在一脸懵逼地翻阅之后,终于找到了始作俑者,是某测试同学发的消息:

“勇哥,我在这个输入框里粘贴️‍这个彩虹旗符号,但是粘贴进去却变成了️白旗符号,这是怎么个情况。。。”

我可能怎么也想不到,这个输入框限制字符数的芝麻粒需求竟然会成为毁坏我技术贞操的朗吉努斯之矛。但作为一个老成的开发,不到最后我绝不会放弃,于是我鲜见地采取了终极的撒手锏 --- 跟同行比烂。我打开了各个平台的昵称输入框,最后在百度的个人账号页面,尝试修改昵称,将文字输入到距离输入上限还差1-2个字符,然后尝试粘贴️‍,哈利路亚!️‍果然变成了️。我立马把这个“振奋人心”的消息发到群里,然后就开始了问题的排查。

原因一定是出在了️‍这个表情符号上。我执行了

Array.from('️‍')
(4) ['', '️', '‍', '']

结果发现得到了4个字符,我感到事情并不简单,于是进行了一通搜索。问题找到了,是word joiner的问题。

word joiner,也称为零宽非中断空格,它的Unicode的点位是U+2060,正是上述四个字符中的第三个不可见字符。它的作用一方面是影响换行时是否将文字拆开,对于一些不使用空格进行分词的语种例如中文,浏览器可能不一定能确切知道一个词是由哪几个中文字符构成的,但如果两个中文字符中间使用了word joiner,那么浏览器就认为这是一整个不可拆分的词,在换行时也会避免将其分开。但当它位于两个表情字符中间的时候,就会有特殊的效用,某些表情字符的组合会成为一个新的表情符号。例如:

Array.from('‍‍')
['', '‍', '', '‍', '']

一家三口的表情,实际上是由男人+女人+小孩的表情通过word joiner连接产生的。

Array.from('‍')
(3) ['', '‍', '']

红头发的男人的表情,实际上是由男人+红色头发表情通过word joiner连接产生的。

此时我立刻就会想到,并不是所有的字符渲染引擎都能够完美支持word joiner

在钉钉中我发送这个一家3口表情,发送编辑器中支持渲染这个组合表情,但发送出之后,在消息框中却没有正确渲染出来。妈妈和孩子组合成了母子表情,但爸爸被孤立成一个字符进行渲染了。。。微信中收发消息都是一致的,均可以正确渲染。组合表情的渲染是依赖于具体的文本渲染引擎的。即便渲染效果不能保证,但降级后的效果一定程度上还是可以忍受的(家散了至少孩子他妈还在)。

但对于输入来说,字符限制通常会对于文本输入进行裁切,就会导致只输入了部分unicode字符的情况发生

Array.from('️‍')
(4) ['', '️', '‍', '']

例如彩虹旗的情况下,如果当前输入框还剩1个字符可以输入,那么后面的字符都会被裁切掉,用户输入进去的自然就只剩一个白旗了。因此解决办法就是不允许进行输入内容裁切,如果用户输入的内容超过了限制长度,输入内容整体都应当被阻止。这也是twitter在个人账户页面昵称输入时采取的策略。

好了,以上就是一个老成的程序员花几天的时间才搞定这个文本输入字符数限制的问题。其实写到这里我已经不知道这到底写了个啥,还要不要发出去了,不过,都晚上十点半了,whatever

相关文章
|
2月前
|
人工智能 小程序 算法
分享64个JavaGame源码总有一个是你想要的
分享64个JavaGame源码总有一个是你想要的
81 0
|
2月前
|
人工智能 Java 关系型数据库
分享66个JavaGame源码总有一个是你想要的
分享66个JavaGame源码总有一个是你想要的
116 0
|
2月前
|
Python
【分享代码】国庆氛围不能少,快来给头像加个国旗
【分享代码】国庆氛围不能少,快来给头像加个国旗
29 0
|
12月前
|
存储 编译器 C语言
还在为每次打开程序的输入烦恼吗,这篇文章让你不在迷茫
在之前我们编写的程序中,我们总要录入一些数据给予程序用于计算,但是当我们退出程序后录入的数据会销毁,因为此时数据都是存放在内存中。等到下次再运行程序时,数据又得从新录入,这样就非常的难受。
45 0
还在为每次打开程序的输入烦恼吗,这篇文章让你不在迷茫
|
10月前
|
移动开发 前端开发 开发者
|
10月前
|
人工智能 移动开发 测试技术
你的交互文档写的好不好?一看便知!
你的交互文档写的好不好?一看便知!
94 0
|
12月前
|
搜索推荐 小程序 程序员
看过很多教程,却依然写不好一个程序,怎么破?
最近在和学员的沟通中,发现不少初学者面临这样一个问题:了解了一些基本的语法,看得懂书上的示例,但是面临一个新的编程问题时,依然感到无从下手。
找不到“妹”字在哪?一款游戏看把你愁的,用我这个代码逻辑,不再被游戏困扰!
找不到“妹”字在哪?一款游戏看把你愁的,用我这个代码逻辑,不再被游戏困扰!
136 0
找不到“妹”字在哪?一款游戏看把你愁的,用我这个代码逻辑,不再被游戏困扰!
|
SQL 存储 监控
聊聊那些年遇到过的奇葩代码
无论是开发新需求还是维护旧平台,在工作的过程中我们都会接触到各种样式的代码,有时候会碰到一些优秀的代码心中不免肃然起敬,但是更多的时候我们会遇到很多奇葩代码,有的时候骂骂咧咧的吐槽一段奇葩代码后定睛一看作者,居然是几个月以前自己的写的,心中难免浮现曹操的那句名言:不可能,绝对不可能。
聊聊那些年遇到过的奇葩代码
|
存储 算法 安全
我用一个小小的开放设计题,干掉了40%的面试候选人
去年团队招聘需求比较大,本人参与了近百次的面试工作。今天来跟大家聊聊,面试候选人过程中,一个常见的开放类设计题目的解题思路,以及候选人的理解设计误区分析。
我用一个小小的开放设计题,干掉了40%的面试候选人