现代浏览器都支持的事件
- click
- dbclick
- mouseover
- mousemove
- mouseout
- focus
- blur
- change(表单输入框特有)
- submit(表单特有)
addEventListener/removeEventListenr
- 注意如果第二个参数是匿名函数的话,不销毁这个元素节点则监听不会停止;
第三参数 | 对应事件 | 效果 | 取消事件 |
---|---|---|---|
true | 事件捕捉 | 从外向内传播 | |
false | 事件冒泡 | 从内向外传播 | e.stopPropagation() |
- 阻止默认行为:
e.preventDefault() / return false
事件对象
- 事件类型
- bubbles: 表示事件是否通过DOM以冒泡形式触发
- 环境信息属性
- button:表示鼠标所按下的按钮
- 0:左
- 1:中
- ctrlKey/altKey/shiftKey 表示是否按下相应键
- button:表示鼠标所按下的按钮
- 键盘事件属性
- isChar:表示当前按下的键是否表示一个字符
- charCode:表示当键的unicode值(仅对keypress有效)
- keyCode:表示非字符按键的unicode值
- which:表示当前按键的unicode值,不管是否是字符
- 事件发生的环境参数
- pageX/pageY:相对于可视区域的坐标
- screenX,screenY:想对于屏幕的坐标
- 和事件相关的元素
- currentTarget:事件冒泡阶段当前所在的DOM元素
- target,originateTarget:原始的DOM元素
- relatedTarget:其他和事件相关的DOM元素(有的话)
切换上下文
- 在addEventListener()方法中的执行函数中,上下文已经切换到当前监听的节点,如果想改变,请使用之前提到的方法
事件委托
- 从冒泡事件开始就开始了事件委托;可以直接给父元素绑定事件监听
list.addEventListener("click", function(e) {
if(e.currentTarget.tagName == "LI") {
/**/
}
}, false)
自定义事件
以jquery插件为例;下面代码使用自定义事件让代码变得整洁,在点击选项卡时触发一个change.tabs事件,并绑定若干回调方法来修改active类
<ul id="tabs">
<li data-tab="user">Users</li>
<li data-tab="group">Groups</li>
</ul>
<div id="tabsContent">
<div data-tab="user">user</div>
<div data-tab="group">group</div>
</div>
jQuery.fn.tabs = function(control) {
var elem = $(this);
control = $(control);
elem.on("click", "li", function() {
var tabName = $(this).attr("data-tab");
elem.trigger("change.tabs", tabName);
});
elem.on("change.tabs", function(e, tabName) {
elem.find("li").removeClass("active");
elem.find(">[data-tab='" + tabName + "']").addClass("active");
});
elem.on("change.tabs", function(e, tabName) {
control.find(">[data-tab]").removeClass("active");
control.find(">[data-tab='" + tabName + "']").addClass("active");
});
//将切换选项卡的动作和窗口的hash做关联,这样可以使用浏览器的退后按钮
elem.on("change.tabs", function(e, tabName) {
window.location.hash = tabName;
});
$(window).on("hashchange", function() {
var tabName = window.location.hash.slice(1);
elem.trigger("change.tabs", tabName);
})
var firstName = elem.find("li:first").attr("data-tab");
elem.trigger("change.tabs", firstName);
return this;
}
$("ul#tabs").tabs("#tabsContent");
DOM无关事件
- 基于事件的编程可以使应用框架充分解耦,事件本质上是和DOM无关的,因此可以开发事件驱动的库;
- 这种模式称为发布/订阅的消息模式,发布者和订阅者是完全解耦的,彼此不知道对方的存在,两者仅仅共享一个信道名称;
- 应用这种模式只需要记录回调和事件名称的对应关系及调用他们的方法;
var PubSub = {
//订阅
subscribe: function(ev, callbacks) {
//双重赋值
var calls = this._callbacks || (this._callbacks = {});
(this._callbacks[ev] || (this._callbacks[ev] = [])).push(callbacks);
return this;
},
//发布
publish: function() {
var args = Array.prototype.slice.call(arguments, 0);
var ev = args.shift();
var list, calls, i, l;
if(!(calls = this._callbacks)) return this;
if(!(list = this._callbacks[ev])) return this;
for(i = 0, l = list.length; i < l; i++) list[i].apply(this, args);
return this;
}
}
PubSub.subscribe("wem", function() {});
PubSub.publish("wem");
//可以使用命名空间的方式管理事件名称
PubSub.subscribe("user:create", function() {});
将其扩充到一个局部对象
var Asset = {};
jQuery.extend(Asset, PubSub);
Asset.subscribe("test", function() {alert("test")});
Asset.publish("test");
使用jquery实现该模式
(function($) {
var o = $({});
$.subscribe = function() {
o.bind.apply(o, arguments);
};
$.unsubscribe = function() {
o.unbind.apply(o, arguments);
};
$.publish = function() {
var arguments = $.makeArray(arguments);
var type = arguments[0];
arguments.shift();
o.trigger.apply(o, [type, arguments]);
}
})(jQuery);
$.subscribe("/some/topic", function(event, a, b, c) {
console.log(event.type, a + b +c);
});
$.publish("/some/topic","a","b","c");