Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
217 views
in Technique[技术] by (71.8m points)

移动端tap事件无视disabled属性?

移动端项目中获取手机验证码的操作,其中引用到jquery-2.2.4.min.jsjquery.mobile.custom.min.js,代码如下:
html:
<input class="code_btn" type="button" value="获取验证码" />
js:

    /* 点击获取验证码 */
    $(document).on('tap', '.code_btn', function () {
      if (!/^[1]([3-9])[0-9]{9}$/.test($('.mobile_input').val())) {
        toast.show('手机号码格式不正确');
      } else {
        countDown();   //倒计时函数
        getMobileCode($('.mobile_input').val());
      }
    });

问题:
image
点击获取验证码按钮后,开始倒计时,并且按钮已有disabled属性,理想状态是:此时该按钮是禁用状态,并不可点击。但现实是:依然可以点击触发tap事件。
后来将tap改为click事件后,就一切正常(按钮禁用,不会触发点击事件),但并不明白其中原理,希望能帮忙解答下~


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

根据 jQuery Mobile API 文档的描述,tap 事件背后是 vclick 事件:

Warning: Use tap with caution
Tap makes use of vclick and therefore should be used with caution on touch devices. See the vclick API documentation for more details.

vclick 文档似乎没有写明实现方式。找源码粗略地看了一下,在移动端应该是使用的 touchend 事件。

// jquery.mobile-1.4.5.js
// ...
// Line 3587 - 3621:
function handleTouchEnd( event ) {
  if ( blockTouchTriggers ) {
    return;
  }

  disableTouchBindings();

  var flags = getVirtualBindingFlags( event.target ),
    ve, t;
  triggerVirtualEvent( "vmouseup", event, flags );

  if ( !didScroll ) {
    ve = triggerVirtualEvent( "vclick", event, flags );
    if ( ve && ve.isDefaultPrevented() ) {
      // The target of the mouse events that follow the touchend
      // event don't necessarily match the target used during the
      // touch. This means we need to rely on coordinates for blocking
      // any click that is generated.
      t = getNativeEvent( event ).changedTouches[ 0 ];
      clickBlockList.push({
        touchID: lastTouchID,
        x: t.clientX,
        y: t.clientY
      });

      // Prevent any mouse events that follow from triggering
      // virtual event notifications.
      blockMouseTriggers = true;
    }
  }
  triggerVirtualEvent( "vmouseout", event, flags);
  didScroll = false;

  startResetTimer();
}
// ...
// Line 3679 - 3680:
          $document.bind( "touchstart", handleTouchStart )
            .bind( "touchend", handleTouchEnd )
// ...

而在 HTML 5.x 标准里,input 元素的 disabled 属性的值被进一步表述为 form control 的状态,可以参阅 The input element - HTML 5.1 2nd Edition: 4.10. Forms | w3.org。同时,一个 disabled 了的 form control 被设定为不接收任何用户指定的 click 事件:

A form control that is disabled must prevent any click events that are queued on the user interaction task source from being dispatched on the element.

MDN 对 input 元素 disabled 属性的描述中也可以找到相关说明:(个人认为中文版翻译得有问题,就不放了。)

Specifically, disabled inputs do not receive the click event, and disabled inputs are not submitted with the form.

所以 touchend 事件不会被屏蔽,tap 事件自然也会正常触发,click 事件则被阻止。


  1. tap | iQuery Mobile API Documentation
  2. vclick | iQuery Mobile API Documentation
  3. jquery.mobile-1.4.5.js
  4. HTML 5.1 2nd Edition: 4.10. Forms | w3.org
  5. <input>: The Input (Form Input) element | MDN

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...