1、实例
1、普通的事件绑定
<div id = 'box'>box</div>
$("#box").on("click",{name:'sunlike'},function(ev){
// 参数1 type 事件类型
// 参数2 data 传入的参数
// 参数3 fn 回调函数
console.log(ev.data.name)
})
// 点击的时候输出sunlike2、事件委托delegate()
<div id = 'box'>box</div>
$("body").delegate("#box","click",function(ev){
// 参数1 obj 实际要触发事件的节点
// 参数2 type 事件类型
// 参数3 fn 回调函数
console.log(123)})// 点击的时候输出123// 实际上是调用的是on//
delegate:function(seletor,types,data,fn){//
return this.on(types,selector,data,fn)//
}3、事件委托on()
<div id = 'box'>box</div>
$("body").on("click","#box",{name:"sunlike"},function(ev){
// 参数1 obj 实际要触发事件的节点
// 参数2 type 事件类型
// 参数3 data 传入参数
// 参数4 fn 回调函数
console.log(ev.data.name)
})
// 点击的时候输出sunlike 4、同时绑定多个事件on()
$("#box").on({
"click", function() {
console.log(123)
}
},
{
"mouseover", function() {
console.log(456)
}
})
// 鼠标移入输出456
// 点击的时候输出123
<div id = 'box'>box</div>
$("#box").one("click",{name:'sunlike'},function(ev){
// 参数1 type 事件类型
// 参数2 data 传入的参数
// 参数3 fn 回调函数
console.log(ev.data.name)
})
// 点击的时候输出sunlike 6、trigger()主动触发事件
<input id = 'name'/>
$("#name").focus(function(){
console.log(123)
})
$("#name").trigger("focus");
// 输出123
// 光标的的聚焦行为也会被触发 7、triggerHandler主动触发事件
<input id = 'name'/>
$("#name").focus(function(){
console.log(123)
})
$("#name").triggerHandler("focus");
// 输出123
// 光标聚焦行为没有触发
// 添加了阻止默认事件和冒泡事件 8、trigger()主动触发自定义事件
<input id = 'name'/>
$("#name").show(function(){
console.log(123)
})
$("#name").trigger("show");
// 输出1239、实现简单的事件绑定、事件解绑
<div id = 'div1'>
<span id = 'span1'></span>
</div>
window.onload = function(){
let mDiv = document.getElementById("div1");
let mSpan =document.getElementById("span1");
var bar = function(){
console.log("bar");
}
var foo = function(){
console.log("foo")
}
add(mDiv,"show",bar);
add(mSpan,"click",foo);
trigger(mDiv,"show");
}
//实现
function add(obj,types,fn){
// 将事件添加到对应的事件列表里
// 并且给节点添加事件
obj.listeners = obj.listeners||{};
obj.listeners[types] = obj.listeners[types]||[];
obj.listeners[types].push(fn);
obj.addEventListener(types,fn,false)
}
function remove(obj,types,fn){
// 移除节点事件
// 并且删除事件列表里对应的事件
obj.removeEventListener(types,fn,false);
delete obj.listeners[types];}function trigger(obj,types){
// 循环执行事件列表里面的绑定的函数
var arr =obj.listeners[types];
for(var i=0;i<arr.length;i++){
arr[i]();
}
}
// 大量事件挂载到DOM节点可能会造成内存泄漏
// 所以jq使用data数据缓存来保存事件数据10、事件缓存的结构
// 代码
<div id = 'box'>
<span id = 'span1'></span>
</div>
$(function(){
$("#div").on("click",function(a){
console.log("普通点击事件a");
})
$("#div").on("click",function(b){
console.log("普通事件b")
})
$("body").on("click","#box",function(c){
console.log("body代理事件c")
})
$("#div").on("click","#span1",function(d){
console.log("div代理事件e")
})
$("#div").on("click.aaa",function(e){
console.log("命名空间aaa事件")
})
$("#div").on("mouseover",function(f){
console.log("mouseover事件")
})
$("#div").on("mouseenter",function(g){
console.log("mouseenter事件")
})
})
// 数据缓存结构
var elemData = {
events:{
'click':[
// arr 有arr.length=2,arr.delegateCount = 1属性
// delegate 事件委托的个数
{
// 委托的项放到首位
data: undefined,
guid:3, // 当前事件的唯一标识
handler:function(d){},// 绑定的事件的事件函数
namespace:"",//命名空间
needsContext: false,
origType:"click",
selector:'span',
type:"click"
},
{
data: undefined,
guid:3,
handler:function(){},
namespace:"",
needsContext: false,
origType:"click",
selector:undefined,
type:"click"
},
{},
{},
{}
]
'mouseover':[
{},
{
data: undefined,
guid:3,
handler:function(){},
namespace:"",
needsContext: false,
origType:"mouseenter",// 原始类型,
selector:undefined,
type:"mouseover",//真正的已经模拟成mouseover
}
],
handle:function(e){
// 真正的事件函数
}
}}11、命名空间
$("#div").on("click",function(){
// 指定一个命名空间aaa
console.log(1);})
$("#div").on("click.aaa",function(){
// 指定一个命名空间aaa
console.log(2)})
$("#div").trigger("click.aaa");
// 只输出1,因为只触发了aaa命名空间绑定的事件12、同时绑定多个事件
<div id = 'box'>
<span id = 'span1'></span>
</div>
$("#div").on("click mouseover",function(){
console.log("同时给节点绑定一个click和mouseover事件");
})
// 只要用空格隔开,事件类型的个数是没有限制的13、pageX、pageY兼容
// 不是所有的浏览器都支持
event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 )
- ( doc && doc.clientLeft || body && body.clientLeft || 0 );
event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 )
- ( doc && doc.clientTop || body && body.clientTop || 0 ); 14、keyCode、charCode
document.onkeyup(function(event){
console.log(event.keyCode)
console.log(event.charCode);
// 兼容比较好的
})2、源码实现
1、jQuery.Event = fucntion(src,props){}
// 事件对象(构造函数),采用的是面向对象的编程思想
jQuery.Event = function( src, props ) {
// Allow instantiation without the 'new' keyword
if ( !(this instanceof jQuery.Event) ) {
return new jQuery.Event( src, props );
}
// Event object
if ( src && src.type ) {
this.originalEvent = src;
this.type = src.type;
// Events bubbling up the document may have been marked as prevented
// by a handler lower down the tree; reflect the correct value.
this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
// Event type
} else {
this.type = src;
}
// Put explicitly provided properties onto the event object
// 将属性继承到当前对象
if ( props ) {
jQuery.extend( this, props );
}
// Create a timestamp if incoming event doesn't have one
this.timeStamp = src && src.timeStamp || jQuery.now();
// Mark it as fixed
// 设置缓存
this[ jQuery.expando ] = true;
};2、jQuery.Event.prototype = {}
// 事件对象原型(构造函数),采用的是面向对象的编程思想
jQuery.Event.prototype = {
// 设置三个阻止事件的属性
isDefaultPrevented: returnFalse,
isPropagationStopped: returnFalse,
isImmediatePropagationStopped: returnFalse,
// 阻止冒泡事件
preventDefault: function() {
var e = this.originalEvent;
this.isDefaultPrevented = returnTrue;
if ( !e ) {
return;
}
// preventDefault()函数存在
if ( e.preventDefault ) {
e.preventDefault();
} else {
// IE某些不支持preventDefault
e.returnValue = false;
}
},
// 阻止默认事件
stopPropagation: function() {
var e = this.originalEvent;
this.isPropagationStopped = returnTrue;
if ( !e ) {
return;
}
//preventDefault函数存在
if ( e.stopPropagation ) {
e.stopPropagation();
}
// 兼容某些IE不支持preventDefault
e.cancelBubble = true;
},
// 相同元素的其他事件会被阻止掉
stopImmediatePropagation: function() {
this.isImmediatePropagationStopped = returnTrue;
this.stopPropagation();
}};3、jQuery.event = {}
jQuery.event = {
global: {},
add:function(){// 添加事件},
remove:function(){// 事件移除},
trigger:function(){ // 事件触发},
dispatch:function(){// 分发事件},
handlers:fucntion(){},
fix:fucntion(){//对event事件进行兼容},
fixHooks: {//事件兼容处理},
keyHooks:{//键盘事件兼容处理},
special:{//特殊事件处理}
simulate:function(){// 事件模拟}
}4、jQuery.fn.extend
// 暴露在外的实例函数
jQuery.fn.extend({
on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
var type, origFn;
// Types can be a map of types/handlers
if ( typeof types === "object" ) {
// ( types-Object, selector, data )
if ( typeof selector !== "string" ) {
// ( types-Object, data )
data = data || selector;
selector = undefined;
}
for ( type in types ) {
this.on( type, selector, data, types[ type ], one );
}
return this;
}
if ( data == null && fn == null ) {
// ( types, fn )
fn = selector;
data = selector = undefined;
} else if ( fn == null ) {
if ( typeof selector === "string" ) {
// ( types, selector, fn )
fn = data;
data = undefined;
} else {
// ( types, data, fn )
fn = data;
data = selector;
selector = undefined;
}
}
if ( fn === false ) {
fn = returnFalse;
} else if ( !fn ) {
return this;
}
// one()事件绑定一次性事件
if ( one === 1 ) {
origFn = fn;
fn = function( event ) {
// 先把事件取消掉,再另外触发事件
jQuery().off( event );
return origFn.apply( this, arguments );
};
// Use same guid so caller can remove using origFn
// 添加函数唯一标识,当方便移除函数
fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
}
// 把事件列表使用add()函数进行进步一处理
return this.each( function() {
jQuery.event.add( this, types, fn, data, selector );
});
},
one: function( types, selector, data, fn ) {
return this.on( types, selector, data, fn, 1 );
},
off: function( types, selector, fn ) {
var handleObj, type;
if ( types && types.preventDefault && types.handleObj ) {
// ( event ) dispatched jQuery.Event
handleObj = types.handleObj;
jQuery( types.delegateTarget ).off(
handleObj.namespace ? handleObj.origType + "." + handleObj.namespace :
handleObj.origType,
handleObj.selector,
handleObj.handler
);
return this;
}
if ( typeof types === "object" ) {
// ( types-object [, selector] )
for ( type in types ) {
this.off( type, selector, types[ type ] );
}
return this;
}
if ( selector === false || typeof selector === "function" ) {
// ( types [, fn] )
fn = selector;
selector = undefined;
}
if ( fn === false ) {
fn = returnFalse;
}
// 对所有事件执行remove操作
return this.each(function() {
jQuery.event.remove( this, types, fn, selector );
});
},
trigger: function( type, data ) {
return this.each(function() {
jQuery.event.trigger( type, data, this );
});
},
triggerHandler: function( type, data ) {
var elem = this[0];
if ( elem ) {
return jQuery.event.trigger( type, data, elem, true );
}
}
});5、jQuery.each();
// 分别调用方法on或trigger来实现对应的时间绑定
jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
"change select submit keydown keypress keyup error contextmenu").split(" "),
function( i, name ) {
// Handle event binding
jQuery.fn[ name ] = function( data, fn ) {
return arguments.length > 0 ?
this.on( name, null, data, fn ) :
this.trigger( name );
};
});6、jQuery.fn.extend
// 暴露在外的实例奇函数jQuery.fn.extend({
// hover事件
hover: function( fnOver, fnOut ) {
return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
},
// 事件绑定
bind: function( types, data, fn ) {
return this.on( types, null, data, fn );
},
// 事件解绑
unbind: function( types, fn ) {
return this.off( types, null, fn );
},
// 事件代理
delegate: function( selector, types, data, fn ) {
return this.on( types, selector, data, fn );
},
// 取消事件代理
undelegate: function( selector, types, fn ) {
return arguments.length === 1 ? this.off( selector, "**" ) :
this.off( types, selector || "**", fn );
}}
);