美文网首页
微信小程序 - 按钮文本框 “giao-text”

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

作者: Jacob_Jiang | 来源:发表于2019-10-29 18:16 被阅读0次

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

    不多说,先上开源地址吧:
    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
    ... ... ... ...

    相关文章

      网友评论

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

          本文链接:https://www.haomeiwen.com/subject/ynvwvctx.html