微信小程序 - 按钮文本框 “giao-text”

最近因为体验了微信小程序 “百万工具箱” 里面的正则表达式工具,感觉到手机端输入正则表达式中的特殊字符十分的繁琐(反人类)。思前想后,决定撸一个可以解决繁琐输入的文本框组件。

不多说,先上开源地址吧:
npm https://www.npmjs.com/package/giao-text
github https://github.com/oloshe/giao-text

初定开发需求:

普通字符使用自带输入法输入,正则表达式常用字符(如:\ | $ ^ )利用组件提供快速输入。

初定的实现思路:
  1. 声明属性 stringSet,通过传入的字符串,分割成若干个字符,生成字符串数组 stringArray;
  2. 利用 stringArray 循环渲染出若干按钮,形成一个按钮面板;
  3. 为按钮面板的按钮添加 tap 事件,点击按钮输入框添加对应字符。


    初始效果

此时遇到的难点

  1. 点击按钮时,焦点会发生变化。当焦点在输入框上时,手机会显示输入键盘,当焦点不在输入框时,输入键盘自动会收回。点击按钮输入字符后,想要继续键盘输入需要再点击输入框,十分的不友好。
  2. 点击按钮添加文本需要在光标 cursor 之后添加,而不是字符串末。

解决思路

  1. 点击按钮添加文本之后,自动把焦点转移到输入框。
  2. 监听输入框失去焦点(blur)事件,因为该事件会返回光标位置,所以必须等到该事件之后才能添加文本。

流程图

流程图

理清大概流程之后,先从左侧(focus in input)入手。

  1. onBlur 输入框失去焦点事件返回获取光标位置(cursor);
  2. onTap 按钮点击事件返回获取对应文本(text);
  3. 传入两个参数到方法 setText 给输入框文本赋值。

此时遇到的难点(坑)

在这种情况下 setText 必须等两个函数都调用完毕再调用,因为 setText的两个参数要分别从 blur 和 tap 事件获取。那么确认一下顺序,通过赋值的方法把第一个参数存起来,到第二个事件调用的时候再执行 setText 函数不就行了?

给两个事件加上打印函数,运行看看打印结果。

onBlur(event) {
 console.log('Blur');
}
onTap(event) {
  console.log('Tap');
}

打印结果

Blur
Tap

如果这时你按照这个结果去设计,你就掉坑了!手机调试时输出的结果刚好时相反的!所以必须不管哪个函数先调用,都要等到两个函数调用完毕再执行 setText。所以在某一个函数加 if 判断是不可行的。但是在两边都加 if 判断又显得十分地不优雅,那怎么办呢?

解决方案

  1. 在 Blur 函数调用 setData 把 cursor 保存;
  2. 在 Tap 函数调用 setData 把 text 保存;
  3. 分别添加 cursor 和 text 的数据监听,当两个字段修改时,调用对应函数;
  4. 添加字段 _tapEvent 、 _blurEvent 记录两个事件的调用情况,取值 0 或 1;
  5. 添加 _tapEvent, _blurEvent 数据监听器,当两个字段都为 1 时,调用 setText。
概念图

代码(部分)

observers:{
  "_cursor": function(_cursor) {
    this.setData({ _blurEvent: 1 })
  },
  "_text": function (_text) {
    this.setData({ _tapEvent: 1 })
  },
  "_blurEvent, _tapEvent": function(blur,tap) {
    if (blur === 1 && tap === 1) {
      this._setText(this.data._cursor,this.data._text);
    }
    setTimeout(() => {
      this.data._tapEvent = 0;
      this.data._blurEvent = 0;
    },200);
  }
},
methods:{
  onBlur(event) {
    let { cursor } = event.detail;
    this.focused = false;
    this.setData({ _cursor: cursor });
    this.triggerEvent('blur',cursor);
  },
  onTap(event) {
    const { index } = event.currentTarget.dataset;
    let _text = this.data.stringArray[index];
    this.setData({ _text: _text });
  },
 _setText(cursor,text) {
    let value = this._insertString(this.data.value,cursor,text);
    cursor = this.data._cursor +  text.length;
    this.setData({
      value,
      cursor,
      focus: true,
    });
    this.triggerEvent('change',value);
  },
  _insertString(str,index,insertStr) {
    return str.slice(0,index) + insertStr + str.slice(index);
  }
}

_blurEvent, _tapEvent 监听器中 setTimeout 的作用是及时清空事件状态,200为该事件时存在时长,作用是让 blur 和 tap 事件的时间误差增大到 200ms,这样不管谁先谁后,两个函数在这 200ms 内都执行了就调用 setText 方法。

ps:如果在这期间某个方法执行多次也不会造成错误,都不会出错,因为数据都存在。

第二种情况

解决了左侧(focus in input)的问题,右侧(focus not in input)的问题就迎刃而解,只需要在 _text 监听器时判断是否有焦点,有焦点就是左侧的问题,如果没有焦点,则直接执行 setText 方法,因为他并不需要等待 blur 函数 或者 _cursor 的值,因为焦点不在输入框上,不会触发 blur 事件,而 cursor 的值直接取即可,cursor 值不会清除。

代码

"_text": function (_text) {
    if (this.focused) {
      this.setData({
        _tapEvent: 1,
      })
    } else {
      this._setText(this.data._cursor, this.data._text);
    }
  },

小结

至此,初定的需求已经解决了。该组件将会不断完善,一直在往可拓展性、实用性的方向发展。

该组件目前解锁了很多实用有趣的功能!将会在微信小程序“百万工具箱”最新版本的正则表达式中应用,感兴趣的小伙伴欢迎前来一看!

百万工具箱

正则表达式组件试用

API(部分)

参数 说明 类型 默认值
string-set 字符集 String -
separator 分隔符,用于分割stringSet String ''
columns 列数,每行的最大按钮个数 Number 6
distinct 是否去重 Boolean false
combo 字符长度为2时,是否将光标移至中间 Boolean false
clearable 是否显示清除按钮 Boolean false
random 按钮是否随机分配位置(在每次输入框获取焦点时) Boolean false
control-keep 按钮面板是否保持显示 Boolean false
scroll 是否为滚动显示(单行) Boolean false
... ... ... ...
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269