代码之家  ›  专栏  ›  技术社区  ›  Denis Hoctor

IE中的事件处理

  •  2
  • Denis Hoctor  · 技术社区  · 14 年前

    下面包含的代码允许我在用户第一次将鼠标悬停在某个元素上然后删除该事件时执行某些操作。

    它在W3C事件模型浏览器中运行得很好,但在IE6-8中不断抛出错误。我从另一个问题中得到了代码,并相信它能解决问题。

        <script type="text/javascript">
        function setMouseEvent() {
            //Tel: 01 8279 400
            event = addEvent(document.getElementById('contactButton'), 'mouseover', changeText);
        }
    
        function changeText() {
            alert("worked!");
            removeEvent(document.getElementById('contactButton'), 'mouseover', changeText);
        }
    
        function addEvent(obj, type, fn) {
            if (typeof obj.addEventListener != undefined) {
                obj.addEventListener(type, fn, false);
            }
            else if (typeof obj.attachEvent != undefined) {
                obj.attachEvent("on" + type, fn);
            }
        }
    
        function removeEvent(obj, type, fn) {
            if (typeof obj.addEventListener != undefined) {
                obj.removeEventListener(type, fn, false);
            }
            else if (typeof obj.attachEvent != undefined) {
                obj.detachEvent("on" + type, obj[type + fn]);
                obj[type + fn] = null;
                obj["e" + type + fn] = null;
            }
        }
    
        window.onload = setMouseEvent;
    </script>
    

    更新: 我刚在最新的Chrome、Opera和FF中进行了测试,没有出现任何问题,但是当我将鼠标移到上面时,Safari什么也不做,IE将错误上传到上面提到的。

    2 回复  |  直到 14 年前
        1
  •  5
  •   bobince    14 年前
    event = addEvent(
    

    addEvent 不返回任何内容;您正在分配 undefined 缺少全局变量的返回值 event (因为你没有说过 var event 在函数中)。这将导致IE中出现异常,它使用 事件 作为将事件详细信息传递给处理程序的特殊对象,因此不允许为其分配其他内容。

    if (typeof obj.addEventListener != undefined)
    

    typeof 始终返回一个字符串,该字符串永远不会测试等于 未定义 unvalue,所以ie总是使用非ie fork并失败。你的意思是 if (typeof obj.addEventListener !== 'undefined') ,使用字符串。

    obj.detachEvent("on" + type, obj[type + fn]);
    

    因为你没有用 type fn 粘在一起的 崇拜者 函数,这将无法检索任何内容。

    正如Crescent所说,你好像在使用Resig's removeEvent 功能,与不同的 崇拜者 那不匹配。如果你用他的 移除事件 你需要用他的 崇拜者 随它去吧。

    不过,我无论如何也不会使用这些函数:它们非常狡猾。我知道这是2005年,这个构思不当的代码赢得了Quirksmode的AddEvent竞赛,但即便如此,我们也应该知道得更多。问题是它从事件名和函数代码的文本序列化创建了一个字符串( type+fn ,并将其用作存储回调的键。这把钥匙看起来像 'mouseoverfunction changeText() {...code...}' .

    但是依靠函数序列化是一个糟糕的想法。格式不由ecmascript标准化(返回函数的依赖于实现的表示形式。有 many browser quirks ;而且,对于浏览器当前的序列化方法,两个不同的函数可以轻松地返回相同的字符串:

    var f1= function() {};
    var f2= function() {};
    

    f1 f2 将具有相同的字符串序列化,但它们不是相同的对象。如果你做了 崇拜者 对于 F1 在IE上,然后是另一个 F2 ,第二个属性将使用相同的序列化字符串并覆盖第一个属性。然后打电话 移除事件 对于 F1 将检索函数 F2 试着 detachEvent 因为功能不同而失败。这个例子看起来可能是做作的,但实际上,当您使用通用闭包时,很容易意外地执行,因为现代的JavaScript现在做的越来越多。因此,我建议 避免Resig's 崇拜者 在任何情况下 .

    (jquery用户:不用担心,因为jquery的所有问题都不会落入使用此代码的陷阱。)

    这个黑客是为了保护 this 当你的价值 changeText 函数由IE调用,其 attachEvent 不设置 . 但你甚至不使用 值,因此您可以使用更简单的版本,例如 original addEvent 它是为替换而创建的。

    至少缺点是 那个 AddEvent是众所周知的,当您在IE上使用 而不仅仅是在某个特定的情况下出错,当它影响到您时,可能会非常混乱并且难以调试。

    同样,您目前还没有为同一个事件使用多个监听器,因此您可以很容易地使用老式的domLevel0事件处理程序,例如:

    window.onload= function() {
        var changed= false;
        document.getElementById('contactButton').onmouseover= function() {
            if (!changed) {
                alert('changing text');
            }
            changed= true;
        };
    };
    
        2
  •  1
  •   gblazex    14 年前

    Dean's addEvent ,如果需要灵活的解决方案:

    // written by Dean Edwards, 2005
    // with input from Tino Zijdel, Matthias Miller, Diego Perini
    // http://dean.edwards.name/weblog/2005/10/add-event/
    
    function addEvent(element, type, handler) {
        if (element.addEventListener) {
            element.addEventListener(type, handler, false);
        } else {
            // assign each event handler a unique ID
            if (!handler.$$guid) handler.$$guid = addEvent.guid++;
            // create a hash table of event types for the element
            if (!element.events) element.events = {};
            // create a hash table of event handlers for each element/event pair
            var handlers = element.events[type];
            if (!handlers) {
                handlers = element.events[type] = {};
                // store the existing event handler (if there is one)
                if (element["on" + type]) {
                    handlers[0] = element["on" + type];
                }
            }
            // store the event handler in the hash table
            handlers[handler.$$guid] = handler;
            // assign a global event handler to do all the work
            element["on" + type] = handleEvent;
        }
    };
    // a counter used to create unique IDs
    addEvent.guid = 1;
    
    function removeEvent(element, type, handler) {
        if (element.removeEventListener) {
            element.removeEventListener(type, handler, false);
        } else {
            // delete the event handler from the hash table
            if (element.events && element.events[type]) {
                delete element.events[type][handler.$$guid];
            }
        }
    };
    
    function handleEvent(event) {
        var returnValue = true;
        // grab the event object (IE uses a global event object)
        event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);
        // get a reference to the hash table of event handlers
        var handlers = this.events[event.type];
        // execute each event handler
        for (var i in handlers) {
            this.$$handleEvent = handlers[i];
            if (this.$$handleEvent(event) === false) {
                returnValue = false;
            }
        }
        return returnValue;
    };
    
    function fixEvent(event) {
        // add W3C standard event methods
        event.preventDefault = fixEvent.preventDefault;
        event.stopPropagation = fixEvent.stopPropagation;
        return event;
    };
    fixEvent.preventDefault = function() {
        this.returnValue = false;
    };
    fixEvent.stopPropagation = function() {
        this.cancelBubble = true;
    };
    
    推荐文章