Ste7en
Ste7en
  • 发布:2016-04-26 12:15
  • 更新:2016-04-26 16:43
  • 阅读:3246

【产品Bug】将checkbox放在label中,另有button都在同一个表单域中,先点击button,之后每次点击checkbox都会触发button的事件,而不会触发checkbox的事件

分类:MUI

详细问题描述
我是在移动web项目中使用的mui,因为mui封装了移动端tap事件,且提供了比较友好的UI。
在页面中使用表单,表单中有button(多个),有checkbox,为了方便点击,将checkbox放在label中,但是先点击button(任意一个),然后在点击checkbox,就会触发刚才点击的button的事件,而checkbox的状态将不会再变化,貌似不会再响应checkbox的事件,在空白处点击一下,就会恢复正常,如此重复。
页面主体代码:

<header class="mui-header mui-bar mui-bar-nav">  
        <a class="mui-action-back mui-btn mui-btn-link mui-pull-left">返回</a>  
        <h1 class="mui-title">开启一键投标</h1>  
    </header>  
    <div class="mui-content mui-scroll-wrapper">  
        <div class="mui-scroll">  
            <div class="mui-content-padded">  
                <form action="" method="post" novalidate="novalidate">  
                    <div class="form-group">  
                        <div class="mui-h4" style="line-height:2;margin-bottom:15px">用户手机号:***********</div>  
                    </div>  
                    <div class="form-group">  
                        <input type="number" name="maxMoney" class="orange" min="0" placeholder="请输入您的最高限额">  
                    </div>  
                    <div class="form-group">  
                        <input type="password" name="payPwd" class="orange" placeholder="请输入您的支付密码">  
                    </div>  
                    <div class="form-group">  
                        <div class="mui-row">  
                            <div class="mui-col-xs-8">  
                                <input type="text" name="capt" class="orange" placeholder="请输入图片验证码">  
                            </div>  
                            <div class="mui-col-xs-4 mui-text-right">  
                                <a id="updateCapt" style="display:block;"><img src="。。。" width="90%" height="40"></a>  
                            </div>  
                        </div>  
                    </div>  
                    <div class="form-group">  
                        <div class="mui-row">  
                            <div class="mui-col-xs-8">  
                                <input type="text" name="phoneCapt" class="orange" placeholder="请输入短信验证码">  
                            </div>  
                            <div class="mui-col-xs-4 mui-text-right">  
                                <button type="button" id="getCode" class="mui-btn mui-btn-red orange mui-btn-outlined" style="padding:0;width:90%;line-height:38px">获取验证码</button>  
                            </div>  
                        </div>  
                    </div>  
                    <p id="getsoundcode" style="margin:0 0 10px;display:none">  
                        <span style="padding:5px 10px;color:#777;border:1px solid #F1D793;background-color:#FFFFE3;">若未收到验证码,请点击 <a style="color:#FF0000;">语音获取</a></span>  
                    </p>  
                    <div class="form-group">  
                        <label><input type="checkbox" checked="checked" name=""> 同意</label>  
                        <a href="。。。">《服务协议》</a>  
                    </div>  
                    <div class="form-group" style="margin-top:15px;">  
                        <button type="submit" class="mui-btn mui-btn-red orange mui-btn-block">确定</button>  
                    </div>  
                </form>  
            </div>  
        </div>  
    </div>  
    <div id="msgModal" class="mui-modal mui-dialog">  
        <div class="mui-modal-header">  
            <div class="mui-modal-title">系统提示</div>  
        </div>  
        <div class="mui-modal-body">  
            <div class="msg-container mui-text-center"></div>  
        </div>  
        <div class="mui-modal-footer">  
            <a href="#msgModal" class="mui-btn">确定</a>  
        </div>  
    </div>  
    <div class="mui-backdrop mui-dialog-mask"></div>

功能js代码如下:

!function(window, $){  
    'use strict'; // 启用严格模式  
    // jquery 静态方法扩展  
    $.extend({  
        /**  
         * json数据加载器  
         * @param param [Object] 同ajax的参数  
         */  
        loader: function (param){  
            param = param || {};  
            var a = param.success || function(){},  
            b = param.error || function(a){  
                alert(a)  
            },  
            c = $.extend({  
                type: 'post',  
                dataType: 'json',  
                cache: false,  
                contentType: 'application/x-www-form-urlencoded;charset=utf-8',  
                complete: function(r){  
                    var a = r.getResponseHeader && r.getResponseHeader('sessionstatus');  
                    a == 'timeout' && (location.href= '。。。')  
                }  
            }, param);  
            c.success = function(c){  
                var f = !1,  
                m = '\u670d\u52a1\u5668\u65e0\u54cd\u5e94',  
                p = {},  
                d = c;  
                if(c) {  
                    if(c.status) {  
                        f = c.status.code === '0000';  
                        m = c.status.msg||'\u8bf7\u6c42\u6210\u529f';  
                        d = c.infoArr || c.infobj || {};  
                        p = c.page || {}  
                    } else {  
                        f = !0;  
                        m = '\u6570\u636e\u52a0\u8f7d\u5b8c\u6210'  
                    }  
                }  
                f ? a.call(this, d, p, m) : b.call(this, m);  
            };  
            return $.ajax(c)  
        }  
    });  

    // jquery对象方法扩展  
    $.extend($.fn, {  
        /**  
         * 将表单元素序列化成对象  
         */  
        serializeObject: function(){  
            var o = {};  
            $.each(this.serializeArray(), function(){  
                if(o[this.name]) {  
                    o[this.name] += ',' + this.value  
                } else {  
                    o[this.name] = this.value  
                }  
            });  
            return o  
        },  
        /**  
         * 通过name获取表单元素的值  
         */  
        getValue: function(n) {  
            return this.serializeObject()[n]  
        },  
        /**  
         * 通过name为表单元素赋值  
         */  
        setValue: function(n, v) {  
            var o = this.find('[name="' + n + '"]').val(v);  
            return this  
        },  
        /**  
         * 表单元素中name和object的key对应载入value  
         */  
        load: function(o){  
            for(var k in o) o.hasOwnProperty(k) && this.setValue(k, o[k]);  
            return this  
        }  
    });  
}(window, jQuery);  
!function(mui, $, window, document, undefined){  

    var methods = {  
        init: function(){  
            mui.init({swipeBack: true});  
            mui('.mui-scroll-wrapper').scroll();  
            this.path = window.contextPath;  
            this.mask = mui.createWaiting();  
            this.btn = document.querySelector('#getCode');  
            this.captBtn = document.querySelector('#updateCapt');  
            this.msgModal = document.querySelector('#msgModal');  
            this.dismiss = this.msgModal.querySelector('.mui-btn');  
            this.form = document.querySelector('.mui-content form');  
            this.voiceBtn = document.querySelector('#getsoundcode');  
            this.checkbox = this.form.querySelector('[type=checkbox]');  
            this.shaild = function(){return false};  
            this.msgCB = undefined;  
            this.initEvent();  
        },  
        initEvent: function(){  
            var self = this;  
            this.btn.addEventListener('tap', function(e){  
                e.preventDefault();  
                self.getVerfiCode('。。。', function(){  
                    self.voiceBtn.style.display = 'block';  
                    self.countdown()  
                })  
            });  
            this.captBtn.addEventListener('tap', function(e){  
                e.preventDefault();  
                this.querySelector('img').setAttribute('src', self.path + '。。。' + new Date().getTime())  
            });  
            this.dismiss.addEventListener('tap', function(e){  
                self.msgCB && self.msgCB();  
            });  
            this.form.addEventListener('submit', function(e){  
                e.preventDefault();  
                self.send()  
            });  
            mui(this.voiceBtn).on('tap', 'a', function(e){  
                e.preventDefault();  
                self.getVerfiCode('。。。')  
            });  
            this.checkbox.addEventListener('change', function(e){  
                self.form.querySelector('[type=submit]').disabled = !e.target.checked;  
            });  
            document.addEventListener('touchstart', this.shaild, false);  
            document.oncontextmenu = this.shaild;  
        },  
        msgAlert: function(m, c){  
            this.msgCB = c;  
            this.msgModal.classList.add('mui-active');  
            this.msgModal.querySelector('.msg-container').innerHTML = m || '';  
        },  
        send: function(){  
            var self = this;  
            var data = $(this.form).serializeObject();  
            if(this.validate(data)) {  
                this.mask.show();  
                $.loader({  
                    url: this.path + '。。。',  
                    data: data,  
                    success: function(r, p, m){  
                        self.mask.close();  
                        self.msgAlert(m, function(){  
                            location.href = self.path + '。。。'  
                        })  
                    },  
                    error: function(m){  
                        self.mask.close();  
                        self.msgAlert(m)  
                    }  
                })  
            }  
        },  
        validate: function(data){  
            if(!data.maxMoney) {  
                return !!this.msgAlert('请输入最高限额')  
            }  
            if(!/^[1-9]\d*$/.test(data.maxMoney)) {  
                return !!this.msgAlert('最高限额格式错误,请重新输入')  
            }  
            if(data.maxMoney < 1000){  
                return !!this.msgAlert('最高投标额应不小于1000元')  
            }  
            if(!data.payPwd) {  
                return !!this.msgAlert('请输入支付密码')  
            }  
            var capt = this.validCapt(data.capt);  
            if(!capt) return capt;  
            if(!data.phoneCapt) {  
                return !!this.msgAlert('请输入短信验证码')  
} return true }, getVerfiCode: function(url, fn){ var self = this; var capt = $(this.form).getValue('capt'); if(this.validCapt(capt)) { this.mask.show(); $.loader({ url: this.path + url, data: { type: '0', capt: capt }, success: function(r, p, m){ self.mask.close(); self.msgAlert(m); fn && fn() }, error: function(m){ self.mask.close(); self.msgAlert(m) } }) } }, validCapt: function(capt){ if(!capt) { return this.msgAlert('请输入图片验证码') && !1 } if(!/^[0-9A-Za-z]{4}$/.test(capt)) { return this.msgAlert('验证码输入错误!') && !1 } return !!capt }, countdown: function(){ var self = this; if(this.interval == undefined) this.interval = 60; if(this.interval-- > 0) { this.btn.disabled = true; this.btn.innerText = this.interval + '秒后重试'; setTimeout(function(){ self.countdown() }, 1000) } else { this.btn.disabled = false; this.btn.innerText = '获取验证码' } } }; mui.ready(function(){methods.init()}) }(mui, jQuery, window, document, undefined);

我是在Chrome控制台仿真模式下调试,真机上也测试了,同样的问题

2016-04-26 12:15 负责人:无 分享
已邀请:
DCloud_UNI_FXY

DCloud_UNI_FXY

能否发一个可重现该问题的最小测试工程。方便直接运行测试

  • Ste7en (作者)

    不好意思,这个是我公司项目的一个小功能页面,没法整个发给你,不过我可以模拟一个发给你,重现问题

    2016-04-26 16:21

  • DCloud_UNI_FXY

    回复 Ste7en:嗯。只要能重现问题就行

    2016-04-26 16:26

Ste7en

Ste7en (作者)

@DCloud_MUI_FXY 附件是问题demo,Chrome仿真模式下,先点击获取验证码或者提交按钮,会弹出校验modal,然后点击modal的确定按钮来toggle modal,然后再change同意协议的checkbox,就会触发之前点击的按钮的事件,而不会change checkbox的状态,除非点击页面空白处才会恢复正常

  • Ste7en (作者)

    在真机上也是一样的效果,麻烦看看是怎么回事

    2016-04-26 16:45

  • DCloud_UNI_FXY

    回复 Ste7en:临时解决方案:<a onclick="document.getElementById('msgModal').classList.remove('mui-active');" class="mui-btn">确定</a>

    2016-04-26 19:32

  • Ste7en (作者)

    回复 DCloud_UNI_FXY:请问你这种段是加在什么位置呢,是modal的toggle按钮还是替换表单的提交按钮

    2016-04-27 09:31

  • Ste7en (作者)

    回复 DCloud_UNI_FXY:问题解决了,好像是因为modal的toggle按钮的hash跳转导致的??

    2016-04-27 09:41

  • Ste7en (作者)

    回复 DCloud_UNI_FXY:

    我把toggle按钮的hash属性去掉了,更改了toggle按钮的tap事件回调

    this.dismiss.addEventListener('tap', function(e){

    e.preventDefault();

    self.msgModal.classList.remove('mui-active');

    self.msgCB && self.msgCB();

    });

    同样也能解决问题,看来还真是toggle按钮的hash属性导致的。。

    2016-04-27 09:49

该问题目前已经被锁定, 无法添加新回复