【JS/读书随笔】JavaScript编程精解/Eloquent JavaScript:Chapter 11 浏览器事件

在浏览器中,每个事件都会创建一个事件对象,事件句柄可以查看这些对象。在浏览器里,javascript 是单线程的。

DOM 树“冒泡”:没有被处理的事件可以通过 DOM 树进行“冒泡”。如果单击一个段落中的链接,任何与链接相关的事件句柄会被首先调用。如果没有事件句柄,或者这些句柄没有表明已经处理完事件,段落(链接的父节点)上的事件句柄就会被触发。然后段落的父节点的事件句柄也会被触发。最后,如果没有处理该事件的 javascript 事件句柄,浏览器会自己对其进行处理。

兼容性:在几乎所有浏览器都基本支持同样功能的事件时,IE 浏览器针对此功能却有完全不同的接口。

处理事件常用操作:

1)注册事件处理句柄(事件处理函数);
2)获得事件对象(e.g. event 对象);
3)从事件对象里提取信息(e.g. event.mouseover);
4)标记事件已经处理了;

详细地讲,1)的方法是设置一个节点的属性对应到事件名称上,例如 onclick 或 onkeypress 。这个方法在不同浏览器上都是有效的,但是它有一个重要缺陷:只能给该元素附加一个事件句柄。还有其他不限制添加事件句柄数量的方法。(假设 button 变量持有一个按钮的 DOM 节点):
IE 浏览器中
button.attachEvent("onclick", function(){alert("Click!");});
其他浏览器中
button.addEventListener("click", function(){print("Click!");}, false);
注意,这里第一个参数 on 是去掉的。第三个参数 addEventListener 是 false,表示事件应该像平常一样通过 DOM 树进行“冒泡”。true 可以使该事件句柄优先级高于其他事件句柄,但是 IE 中不支持,所以很少用到。

function registerEventHandler(node, event, handler){
    if(typeof node.addEventListener(event, handler, false);
    else
        node.attachEvent("on" + event, handler);
}

上面的函数可以查看浏览器支持的是 IE 模型或是其他浏览器模型,并查看能否正常运行。
删除事件句柄的方式和添加句柄几乎一样,不过使用的是 detachEvent 方法和 removeEventListener 方法。

function unregisterEventHandler(node, event, handler){
    if(typeof node.removeEventListener == "function")
        node.removeEventListener(node, handler, false);
    else
        node.detachEvent("on" + event, handler);
}

事件对象正规化代码片:

function normalizeEvent(event){
    if(!event.stopPropagation){
        event.stopPropagation = function(){this.cancelBubble = true;};
        event.preventDefault = function(){this.returnValue} = false;};
}
    if(!event.stop)
        event.stop = function(){
            this.stopPropagation();
            this.preventDefault();
            };

    if(event.srcElement && !event.target)
        event.target = event.srcElement;
    if((event.toElement || event.fromElement) && !event.relatedTarget)
        event.relatedTarget = event.toElement || event.fromElement;
    if(event.clientX != undefined && event.pageX == undefined){
        event.pageX = event.clientX + document.body.scrollLeft;
        event.pageY = event.clientY + document.body.scrollTop;
    }
    if(event.type == "keypress")    
        event.character = String.fromCharCode(event.charCode || event.keyCode);
    return event;

该函数遍历了之前讨论的所有事件对象属性,并确保每个属性都可以在标准的名称下找到。利用这个函数,给 registerEventHandler 和 unregisterEventHandler 编写更方便的包装:

function addHandler(node, type, handler){
    function wrapHandler(event){
        handler(normalizeEvent(event || window.event));
    }
    registerEventHandler(node, type, wrapHandler);
    return{node:node, type:type, handler:wrapHandler};
}

function removeHandler(object){
    unregisterEventHandler(object.node, object.type, object.handler);
}

addHandler 用法,下例为一个文本自动添加一个事件句柄来防止用户输入字母 Q :

var blockQ = addHandler(textfield, "keypress", function(event){
    if(event.character.toLowerCase = "q")
        event.stop();
});

removeHandler(blockQ);

下例中文本输入框有焦点的时候,会将一个输入框的背景编程黄色:

addHandler(textfield, "focus", function(event){
    event.target.style.backgroundColor = "yellow";
});
addHandler(textfield, "blur", function(event){
    event.target.style.backgroundColor = "";
});
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值