zoukankan      html  css  js  c++  java
  • [js]jQuery EasyUI的linkbutton组件disable方法无法禁用jQuery绑定事件的问题分析

    问题由来

    linkbutton 是 jQuery EasyUI 中常用的一个控件,可以使用它创建按钮。用法很简单,使用 a 标签给一个easyui-linkbutton 的class就可以了。

    <a id="btn" class="easyui-linkbutton">这是一个按钮</a>

    或者使用代码方式。

    $("#btn").linkbutton();

    实际使用时,经常会使用 jQuery 添加事件处理函数。例如

       $("#btn").click(function () {
            alert("点击事件");
        });

    在使用过程中可能会需要暂时禁用这个按钮,easyui 已经提供了禁用按钮的方法 disable,使用方法也很简单

    $(function(){
        $("#btn").linkbutton(“disable”);
    })

    到这儿问题就来了,再点击一下,提示框照依然弹了出来,disable方法好像并没有什么效果

    原因分析:不同的事件处理方式

    在 DOM 中,存在着两类不同的事件处理方式,DOM0式和 DOM2 方式。

    DOM0通过在HTML中设置属性,或者在JavaScript中设置一个对象的属性(property)的方法注册事件. 例如

    var btn = document.getElementById("btn");
    btn.onclick = function () {
        alert("clicked");
    };

    取消事件注册,将 onclick 赋予为null 即可

    btn.onclick = null;

    DOM 2通过addEventListener()方法注册事件

    var btn = document.getElementById("btn");
    btn.addEventListener("click", function () {
        alert("clicked");
    }, false);

    通过addEventListener添加的事件只能处理程序只能使用removeEventListener来移除,移除时传入的参数与添加处理程序时使用的参数相同,这也意味着通过addEventListener添加的匿名函数将无法移除

    问题在于,这两种方式是各自独立处理的,互相并不影响。

    由于 easyui 中使用了 DOM0 方式处理按钮的启用和禁用,而 jQuery 则使用 DOM2 方式进行事件的注册,所以之前的禁用失效了。

    使用  DOM Level 0 方式,我们可以通过事件名称,方便地取得原来注册的事件处理函数,保存起来,以便以后回复。这正是 linkbutton 现在已经完成的。

    解决方法:修复 linkbutton 的启用和禁用

    修改的方式就是在原来的基础上,增加对于通过 DOM Level 2 方式注册的事件进行处理。检查是否注册了 jQuery 的 click 事件处理函数,如果有,在数据缓存对象上增加一个名为 savedHandlers 的数组来保存原来的点击事件处理函数,然后,从原来的对象上取消已经注册的事件处理函数。恢复的时候,检查数据对象上是否有保存的事件处理函数数组,如果存在,遍历这个数组,将这些事件处理函数重新注册到元素上。

    function setButtonState(domElem, disabled) {                    // 设置按钮状态
    
        var data = $.data(domElem, "linkbutton");                   // 获取对象的数据
        if (disabled) {                                             // 禁用按钮
            data.options.disabled = true;
            var href = $(domElem).attr("href");                     // 获取超级连接
            if (href) {
                data.href = href;                                   // 保存原来的超级链接
                $(domElem).attr("href", "javascript:void(0)");      // 重新设置
            }
            if (domElem.onclick) {                                  // 是否有点击事件处理
                data.onclick = domElem.onclick;
                domElem.onclick = null;                             // 取消掉
            }
            var eventData = $(domElem).data("events") || $._data(domElem, 'events');
            if (eventData && eventData["click"]) {
                var clickHandlerObjects = eventData["click"];
                data.savedHandlers = [];
                for (var i = 0; i < clickHandlerObjects.length; i++) {
                    if (clickHandlerObjects[i].namespace != "menu") {
                        var handler = clickHandlerObjects[i]["handler"];
                        $(domElem).unbind('click', handler);
                        data.savedHandlers.push(handler);
                    }
                }
            }
    
            $(domElem).addClass("l-btn-disabled");                  // 使用样式
        } else {
            data.options.disabled = false;                          // 启用按钮
            if (data.href) {                                        // 恢复原来的超级链接
                $(domElem).attr("href", data.href);
            }
            if (data.onclick) {                                     // 恢复原来的点击事件处理
                domElem.onclick = data.onclick;
            }
            if (data.savedHandlers) {
                for (var i = 0; i < data.savedHandlers.length; i++) {
                    $(domElem).click(data.savedHandlers[i]);
                }
            }
    
            $(domElem).removeClass("l-btn-disabled");
        }
    }

    如果不想修改easyui的源代码,可以使用扩展方法来解决这个问题

    /**
     * linkbutton方法扩展
     * @param {Object} jq
     */
    $.extend($.fn.linkbutton.methods, {
        /**
         * 激活选项(覆盖重写)
         * @param {Object} jq
         */
        enable: function(jq){
            return jq.each(function(){
                var state = $.data(this, 'linkbutton');
                if ($(this).hasClass('l-btn-disabled')) {
                    var itemData = state._eventsStore;
                    //恢复超链接
                    if (itemData.href) {
                        $(this).attr("href", itemData.href);
                    }
                    //回复点击事件
                    if (itemData.onclicks) {
                        for (var j = 0; j < itemData.onclicks.length; j++) {
                            $(this).bind('click', itemData.onclicks[j]);
                        }
                    }
                    //设置target为null,清空存储的事件处理程序
                    itemData.target = null;
                    itemData.onclicks = [];
                    $(this).removeClass('l-btn-disabled');
                }
            });
        },
        /**
         * 禁用选项(覆盖重写)
         * @param {Object} jq
         */
        disable: function(jq){
            return jq.each(function(){
                var state = $.data(this, 'linkbutton');
                if (!state._eventsStore)
                    state._eventsStore = {};
                if (!$(this).hasClass('l-btn-disabled')) {
                    var eventsStore = {};
                    eventsStore.target = this;
                    eventsStore.onclicks = [];
                    //处理超链接
                    var strHref = $(this).attr("href");
                    if (strHref) {
                        eventsStore.href = strHref;
                        $(this).attr("href", "javascript:void(0)");
                    }
                    //处理直接耦合绑定到onclick属性上的事件
                    var onclickStr = $(this).attr("onclick");
                    if (onclickStr && onclickStr != "") {
                        eventsStore.onclicks[eventsStore.onclicks.length] = new Function(onclickStr);
                        $(this).attr("onclick", "");
                    }
                    //处理使用jquery绑定的事件
                    var eventDatas = $(this).data("events") || $._data(this, 'events');
                    if (eventDatas["click"]) {
                        var eventData = eventDatas["click"];
                        for (var i = 0; i < eventData.length; i++) {
                            if (eventData[i].namespace != "menu") {
                                eventsStore.onclicks[eventsStore.onclicks.length] = eventData[i]["handler"];
                                $(this).unbind('click', eventData[i]["handler"]);
                                i--;
                            }
                        }
                    }
                    state._eventsStore = eventsStore;
                    $(this).addClass('l-btn-disabled');
                }
            });
        }
    });
  • 相关阅读:
    BZOJ2705[SDOi2012]Longge的问题
    Ubuntu 18.04 打不开1.1.0版本网易云音乐的解决方法汇总
    BZOJ3295[CQOI2011]动态逆序对(CDQ分治)
    hdu-4638-Group(树状数组)
    hdu-3333-Turing Tree(树状数组)
    UVA-11983-Weird Advertisement(线段树+扫描线)[求矩形覆盖K次以上的面积]
    ZOJ-3597-Hit the Target!(线段树+扫描线)
    POJ-1177-Picture(线段树+扫描线+离散化)[矩形周长并]
    POJ-1151-Atlantis(线段树+扫描线+离散化)[矩形面积并]
    LightOJ 1135(线段树)
  • 原文地址:https://www.cnblogs.com/masonlu/p/10676625.html
Copyright © 2011-2022 走看看