实例方法和便捷方法是指jQuery可以直接通过链接操作的方法,是通过调用$.event上的方法(上一节介绍的底层方法)来实现的,常用的如下:

  • on(types,selector,data,fn,one)  ;为匹配元素集合中的每个元素绑定一个或多个类型的事件监听函数

    • types          ;事件类型字符串,多个事件类型之间用空格隔开
    • selector      ;可选,是一个选择器表达式字符串,用于绑定代理事件。
    • data            ;传递给事件监听函数的自定义数据,可以是任何类型。
    • fn           ;待绑定的监听函数
    • one                  ;该事件是否只执行一次,为方法.one()提供支持

    writer by:大沙漠 QQ:22969969

  • off(types,selector,fn)  ;移除匹配元素中每个元素上绑定的一个或多个类型的监听函数,参数如下:
    • types               ;一个或多个以空格分隔的事件类型和可选的命名空间
    • selector           ;可选的选择器表达式字符串,用于移除代理事件
    • fn                    ;待移除的监听函数,可以设置为false,表示内部定义的只返回false的函数
  • off(types,selector,fn)   ;移除匹配元素中每个元素上绑定的一个或多个类型的监听函数
    • types        ;一个或多个以空格分隔的事件类型和可选的命名空间
    • selector    ;可选的选择器表达式字符串,用于移除代理事件
    • fn          ;待移除的监听函数,可以设置为false
  • bind(types,data,fn)            ;绑定一个普通事件
  • trigger(type, data)                  执行每个匹配元素上绑定的监听函数和默认行为,并模拟冒泡过程
  • one(types,selector,data,fn)    ;为匹配元素集合中的每个元素绑定最多执行一次的事件监听函数
  • hover(fnOver, fnOut)              ;用于在匹配元素上绑定一个或两个监听函数,当鼠标指针进入和离开时,绑定的监听函数被执行

我们还是以上一节的实例为例,用实例方法改写一下,如下:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="http://libs.baidu.com/jquery/1.7.1/jquery.min.js"></script>
<style>div{width: 200px;padding-top:50px;height: 150px;background: #ced;}div button{margin:0 auto;display: block;}</style>
</head>
<body>
<div>
<button id="button">按钮1</button>
</div>
<script>
$("div").on('click',()=>console.log('div普通单击事件'));
$('div').on('click','button',()=>console.log('d1代理事件'))
</script>
</body>
</html>

渲染如下:

和上一节一样,我们在div上绑定了一个普通事件和代理事件,当点击div时触发普通事件,点击按钮时分别触发普通事件和代理事件。

另外为了更方变使用事件,jQuery还定义了很多的便捷事件方法,可以直接在jQuery实例上调用,注意:便捷方法不能绑定代理事件,只能绑定普通事件,所有的便捷方法如下:

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

我们将上面的例子改写一下,用便捷方法来实现,如下:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="http://libs.baidu.com/jquery/1.7.1/jquery.min.js"></script>
<style>div{width: 200px;padding-top:50px;height: 150px;background: #ced;}div button{margin:0 auto;display: block;}</style>
</head>
<body>
<div>
<button id="button">按钮1</button>
</div>
<script>
$("div").click(()=>console.log('div普通单击事件')); //用便捷事件来实现
$('div').on('click','button',()=>console.log('d1代理事件')) //代理事件不能用便捷方法来操作,因此我们用实例方法来实现
</script>
</body>
</html>

效果和上面是一样的。

源码分析


实例方法是定义在jQuery.fn上的,on主要对参数做一些判断,以支持多种格式的调用方法,实现如下:

jQuery.fn.extend({

    on: function( types, selector, data, fn, /*INTERNAL*/ one ) {    //该方法主要是修正参数。为匹配元素集合中的每个元素绑定一个或多个类型的事件监听函数。
var origFn, type; // Types can be a map of types/handlers //如果types是对象时,即参数格式是.on(Object,selector,data,one)或.one(Object,data,one)则
if ( typeof types === "object" ) {
// ( types-Object, selector, data )
if ( typeof selector !== "string" ) {
// ( types-Object, data )
data = selector;
selector = undefined;
}
for ( type in types ) { //遍历参数types,递归调用方法.on(types,selector,data,fn,one)绑定事件。
this.on( type, selector, data, types[ type ], one );
}
return this;
} if ( data == null && fn == null ) { //如果没有参数3、4,则认为格式是.on(types,fn)
// ( types, fn )
fn = selector; //把第二个参数修正为fn。
data = selector = undefined;
} else if ( fn == null ) { //传入了三个参数时
if ( typeof selector === "string" ) { //如果第二个参数是字符串,则认为格式是:.on(types,selector,fn) 忽略参数data,并把第三个参数作为参数fn。
// ( types, selector, fn )
fn = data;
data = undefined;
} else { //否则则认为忽略参数selector,并把第而个参数作为参数data,并把第三个参数作为参数fn。格式是.on(types,data,fn)
// ( types, data, fn )
fn = data;
data = selector;
selector = undefined;
}
}
if ( fn === false ) { //如果参数fn是布尔值false,则把它修正为总返回false的函数returnFalse()。
fn = returnFalse;
} else if ( !fn ) { //如果fn没有值则直接返回。
return this;
} if ( one === 1 ) { //当方法one()调用.on()时,该参数为1,就会把监听函数fn重新封装为一个只会执行一次的新监听函数。
origFn = fn;
fn = function( event ) {
// Can use an empty set, since event contains the info
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++ );
}
return this.each( function() { //遍历当前的this
jQuery.event.add( this, types, fn, data, selector ); //调用add()绑定事件
});
},
one: function( types, selector, data, fn ) { //为匹配元素集合中的每个元素绑定一个或多个类型的事件监听函数,每个监听函数在每个匹配元素上最多执行一次。该方法简单的通过调用.on(types,selector,data,fn,one)来实现。
return this.on.call( this, types, selector, data, fn, 1 );
},
/*略*/
})

对于便捷方法来说,他就是在$.fn上定义每一个属性,值为一个函数,内部还是调用$.fn.on来实现添加事件的,如下:

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 ) { //参数1是一个数组 参数2是个函数,其中name是值,比如blur、focus // Handle event binding
jQuery.fn[ name ] = function( data, fn ) { //初始化事件便捷方法,在jQuery.fn对象上添加元素,这样jQuery实例就可以直接访问了
if ( fn == null ) { //修正参数,如果只传入一个参数,则把该参数视为fn参数,把data视为null
fn = data;
data = null;
} return arguments.length > 0 ? //根据参数个数决定是绑定事件还是触发事件
this.on( name, null, data, fn ) : //如果参数个数大于1,则调用方法.on()绑定事件监听函数
this.trigger( name ); //如果没有参数,则调用方法.trigger()触发事件监听函数和默认行为
}; if ( jQuery.attrFn ) { //记录事件便捷方法名,在调用jQuery.attr()读取或设置HTML属性时,如果属性名与事件便捷方法名同名,则会改为调用同名的事件便捷方法a
jQuery.attrFn[ name ] = true;
} if ( rkeyEvent.test( name ) ) {
jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;
} if ( rmouseEvent.test( name ) ) {
jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;
}
});

可以看到,如果执行便捷方法时不传递参数将触发该事件,例如:$('div').click()将会触发在该div上绑定的普通事件。

jQuery 源码分析(十七) 事件系统模块 实例方法和便捷方法 详解的更多相关文章

  1. jQuery 源码分析(十一) 队列模块 Queue详解

    队列是常用的数据结构之一,只允许在表的前端(队头)进行删除操作(出队),在表的后端(队尾)进行插入操作(入队).特点是先进先出,最先插入的元素最先被删除. 在jQuery内部,队列模块为动画模块提供基 ...

  2. jQuery 源码分析(二) 入口模块

    jQuery返回的对象本质上是一个JavaScript对象,而入口模块则可以保存对应的节点的引用,然后供其它模块操作 我们创建jQuery对象时可以给jQuery传递各种不同的选择器,如下: fals ...

  3. Vue.js 源码分析(六) 基础篇 计算属性 computed 属性详解

    模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的.在模板中放入太多的逻辑会让模板过重且难以维护,比如: <div id="example">{{ messag ...

  4. Vue.js 源码分析(二十四) 高级应用 自定义指令详解

    除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令. 官网介绍的比较抽象,显得很高大上,我个人对自定义指令的理解是:当自定义指令作用在一些DOM元素或组件上 ...

  5. Vue.js 源码分析(二十二) 指令篇 v-model指令详解

    Vue.js提供了v-model指令用于双向数据绑定,比如在输入框上使用时,输入的内容会事实映射到绑定的数据上,绑定的数据又可以显示在页面里,数据显示的过程是自动完成的. v-model本质上不过是语 ...

  6. Vue.js 源码分析(十四) 基础篇 组件 自定义事件详解

    我们在开发组件时有时需要和父组件沟通,此时可以用自定义事件来实现 组件的事件分为自定义事件和原生事件,前者用于子组件给父组件发送消息的,后者用于在组件的根元素上直接监听一个原生事件,区别就是绑定原生事 ...

  7. Vue.js 源码分析(二十九) 高级应用 transition-group组件 详解

    对于过度动画如果要同时渲染整个列表时,可以使用transition-group组件. transition-group组件的props和transition组件类似,不同点是transition-gr ...

  8. Vue.js 源码分析(二十八) 高级应用 transition组件 详解

    transition组件可以给任何元素和组件添加进入/离开过渡,但只能给单个组件实行过渡效果(多个元素可以用transition-group组件,下一节再讲),调用该内置组件时,可以传入如下特性: n ...

  9. Vue.js 源码分析(二十六) 高级应用 作用域插槽 详解

    普通的插槽里面的数据是在父组件里定义的,而作用域插槽里的数据是在子组件定义的. 有时候作用域插槽很有用,比如使用Element-ui表格自定义模板时就用到了作用域插槽,Element-ui定义了每个单 ...

随机推荐

  1. 【bzoj4555】[Tjoi2016&Heoi2016]求和(NTT+第二类斯特林数)

    传送门 题意: 求 \[ f(n)=\sum_{i=0}^n\sum_{j=0}^i\begin{Bmatrix} i \\ j \end{Bmatrix}2^jj! \] 思路: 直接将第二类斯特林 ...

  2. Nim 游戏

    你和你的朋友,两个人一起玩 Nim 游戏:桌子上有一堆石头,每次你们轮流拿掉 1 - 3 块石头. 拿掉最后一块石头的人就是获胜者.你作为先手. 你们是聪明人,每一步都是最优解. 编写一个函数,来判断 ...

  3. 磕磕绊绊中,使用Git工具完成代码上传

    1.安装Git工具 1)下载并安装Git工具:Git下载地址 安装完成之后,在桌面空白处点击右键,会出现以下选项: 2.初始化环境 1) 在一文件夹中,点击右键,选择上图中的Git Bash Here ...

  4. 【Unity游戏开发】性能优化之在真机上开启DeepProfile与踩坑

    一.引子 最近马三入职了新公司,平时除了负责编辑器开发之外还要做一些游戏性能优化方面的工作.在这里首先给大家安利一下Unity官方的性能测试分析工具URP ,这个工具目前是免费,测试的过程中也不需要接 ...

  5. 如何关闭jdk自动更新提示

    缘由 国庆将电脑重装了一下,jdk自然也就重装了,一开机总是提示我更新,索性就将他关掉. 解决办法 右键这个图标,点击属性. 将自动更新取消勾选.

  6. ASP.NET MVC教程一:ASP.NET MVC简介

    一.MVC模式简介 MVC模式是一种流行的Web应用架构技术,它被命名为模型-视图-控制器(Model-View-Controller).在分离应用程序内部的关注点方面,MVC是一种强大而简洁的方式, ...

  7. 自学_数据库<三>

    数据库 数据库概述 DBMS(DataBase Management System,数据库管理系统)和数据库.平时谈到"数据库"可能有两种含义:MSSQLServer.Oracle ...

  8. MD5是个好东西 / MD5 is a nice guy

    md5是一种摘要生成算法,通过对消息生成唯一摘要,可校验消息是否被篡改. 众所周知,md5广泛用在http接口通讯的安全控制上,通过在签名原始串后加上商户通信秘钥,进行MD5运算,形成的摘要字符串即为 ...

  9. sqlserver查看表空间

    sqlserver 用于查看当前数据库所有表占用空间大小的存储过程 create procedure dbo.proc_getsize as begin create table #temp ( t_ ...

  10. 通过Shell脚本来创建批量服务器上的MySQL数据库账号

    1.项目背景 因监控需要,我们需要在既有的每个MySQL实例上创建一个账号.公司有数百台 MySQL 实例,如果手动登入来创建账号很麻烦,也不现实.所以,我们写了一个简单的shell脚本,用来创建批量 ...