jQuery

jQuery


jQuery能让开发者在文档中轻松找到关心的元素,并对这些元素进行操作: 添加内容,编写HTML属性和CSS属性、定义事件处理程序以及执行动画。它还拥有Ajax工具来发起HTTP请求,以及一些通用的工具函数来操作对象和数组。


jQuery的特性:
丰富强大的语法(css选择器),用来查询文档元素
高效的查询方法,用来找到与css选择器匹配的文档元素集
一套有用的方法,用来操作选中的元素
强大的函数式编程技巧,用来批量操作元素集,而不是每次只操作单个
简洁的语言用法(链式调用),用来表示一系列顺序操作

1. jQuery基础


(1) 全局变量


jQeuery类库定义了一个全局函数: jQuery()。还有另外一个快捷别名: $。这是jQuery在全局命名空间中定义的唯一两个变量。

这个方法拥有两个名字的全局方法是jQuery的核心查询方法,返回值为一个或者多个DOM元素,这就是jQuery对象。返回的是一个类数组对象,而不是一个数组对象。

如下图测试:


jQuery_第1张图片

(2)  DOM元素与jQuery对象之间的转换

DOM元素 -》  jQuery对象: 
对于一个dom对象,只需要用$()把dom对象包装起来,就可以获得一个jquery对象了,方法为$(dom对象);
var divJqueryObject = $('div') 
//不嫌麻烦的话,也可以使用jQuery
var divJqueryObject = jQuery('div') 


jQuery对象 -》 DOM元素: 

var domElement = $('div')[0];
var domElement = $('div').get(0);

(3) jQuery()函数


四种调用方式:


a. css选择器

最常用的调用方式就是传递CSS选择器给$()方法。
第一个参数就是选择器字符串,第二个参数是可选的,可以讲一个元素或者jQuery对象作为第二个参数传递给$()方法。
示例: 

然后请看图示: 有无第二个参数的区别。


jQuery_第2张图片

红色框内实在html元素下进行查询(包含html元素),但是绿色框内的查询实在#div1下的查询(不包含#div1)。


b. 传递一个Element, Document或Window对象给$()方法

这样做的目的只是简单将对象封装成jQuery对象并返回,这样只是为了可以使用jQuery方法操作这些对象而不用使用原生DOM方法。经常可以见到$(document),$(this)。

c. 传递HTML文本字符串

在这种方式下jQuery会根据传入的文本创建好HTML元素并封装成jQuery对象返回。
第一个参数是文本字符串,文本字符串不可传入纯文本,纯文本会被当作css选择器解析。所以这个字符串必须至少包含一个带有尖角括号的HTM的标签。
第二个参数是可选的。
var a = $("", {"href":"www.baidu.com", "css":{"color":"red"}, "text": "baidu"});

Note: 如果我将text提前放到第一个参数里,那么第二个参数里属性起不到作用。所以呢,要不然所有的属性值全放在第一个参数里,或者就放在第二个参数里,不要两边都使用。


d. 传入一个函数给$()方法

这是一种特殊的文档加载行为,当文档加载完毕并且DOM可操作时,传入的函数将会被调用。
$(function() {...}) => $(document).ready(function(){})
通过$()注册的函数将在DOMContentLoaded事件触发时由JQuery触发。当浏览器不支持该事件时,会在load事件出发时由jQuery触发。

(4) 查询和查询结果


传递CSS选择器字符串给$()。它返回的jQuery对象表示匹配(或称为"选中")的元素集。

$()的返回值是一个jQuery对象。jQuery对象是类数组:拥有length属性和介于0~length-1之间的数值属性。

也可以使用size()方法来代替length属性,用get()方法来代替方括号索引。可以使用toArray()方法来将jQuery对象转化为真实数组。请看图示:


jQuery_第3张图片

jQuery对象还有三个挺有趣的属性。
selector:创建jQuery对象时的选择器字符串(如果有的话)。
context:上下文对象,是传递给$()方法的第二参数,如果没有传递的话,默认是Document对象。
jquery:字符串形式的jQuery版本号。

index()方法

该方法接受一个元素作为参数,返回值时该元素在此jQuery对象中的索引值,如果找不到的话,则返回-1.
$('div').index($("#div1")) //0
$('div').index($("#div2")) //1
$('div').index($("#div3")) //2

如果传入的是字符串,index()会把它当做CSS选择器,并返回该jQuery对象中匹配该选择器的一组元素中第一个元素的索引值。对于字符串的方法,其实我不是很了解,测试的结果
$('div').index("#div1")  //0
$('div').index("#div2")  //-1
$('div').index("#div3")  //-1
有种解释是说,当我们使用字符串的时候参数为选择器字符串: 返回div中的第一个元素(即#div1)在选择器"#div2"所匹配的元素中的索引选择器"#div2"匹配的元素只有#div2一个,没有#div1,因此返回-1。虽然不是很了解,希望有知道的同志可以解答一下。

如果没有参数,则是在同级元素中同类元素的索引值。

is()方法

该方法接受一个选择器作为参数,如果选中的元素中至少有一个匹配该选择器时,则返回true。
用上面的html代码:
$('div').is(#div1) //true

2. jQuery的getter和setter


jQuery对象上最简单,最常见的操作就是获取或者设置HTML属性,css样式,元素内容和位置高度的值。


(1) getter和setter概要

a. jQuery使用同一个方法即当getter用又做setter用,而不是定义一对方法,如果传入参数则是当做设置使用,如果没有参数值则是当做获取使用,返回对应值。

b. 用作setter的时候,这些方法会给jQuery对象中的每一个元素设置值,然后返回该jQuery对象以方便链式调用。

c. 用作getter时,这些方法只会查询元素集中的第一个元素,然后返回单个值,如果想要遍历所有的元素,可以使用map方法。后面章节中会提到。

d. 用作setter的时候,这些方法接受对象参数,在这种情况下,该对象的每一个属性都指定一个需要设置的key/value。

e. 用作setter时,这些方法也可以接受函数参数。在这种情况下,会调用函数来计算需要设置的值。调用该函数时的this值是对应的元素,第一个参数是该元素的索引值,当前值则是作为第二个参数传入。

(2) 获取和设置HTML


attr()方法是jQuery中用于HTML属性的getter/setter,然后我们使用上面提到的几种方式。

Test getter/setter function in jQuery

$("a").attr("href"); //www.baidu.com

$("a").attr("href", "www.baidu.com"); //jQuery对象

$("a").attr({target: "_blank", href: "ww.rodchen.com"})

$("a").attr("target", function(x, y) {
			   		console.log(this);  //Test getter/setter function in jQuery
			   		console.log(x);     //0
			   		console.log(y);     //_balank
			   })


(3) 获取或者设置css属性


css方法和attr基本上相同,只是css方法作用域元素的CSS样式,这里主要说出一些不同的地方。

a. CSS样式名可以使用连字符或者使用驼峰格式JavScript样式名

对于驼峰样式名的好处在于:可以再js如下面访问的方式。


var styles = $('.active').css(['width' , 'height' , 'backgroundColor']) ;

console.log( '获取到的宽度值为:' + styles.width ) ;
console.log( '获取到的高度值为:' + styles.height ) ;
console.log( '获取到的背景色为:' + styles.backgroundColor ) ;


b. 获取样式的时候,css会自动将数值装换为带有单位后缀的字符串返回


(4) 获取和设置CSS类


class属性名在JavaScript中通过className / class访问,会被解析成一个空格分割的CSS类名列表。


在jQuery中有下面的方法来操作class属性
addClass   : 添加class
removeClass: 删除class
toggleClass:  当元素还没有某些类时,给元素加上这些类,如果有了,则是删除这些类
hasClass   :  判断类是否存在


(5) 获取和设置表单值


val()用来设置和获取HTML表单元素的value属性


(6) 设置和获取元素内容

jQuery中使用text()来获取和设置元素的纯文本。使用html()来获取和设置HTML内容。

text()对应js中的textContent(IE8及以前版本不兼容)/ innerText属性。
html()对应js中innerHTML属性

text & html方法也可以接受function作为参数。

(7) 获取和设置元素数据


data() / removedata(),用法就不提了,看一下data存在的意义。

data有什么作用?

在我们平时js编码过程中,我们经常会向DOM元素中添加各种自定义属性,这样有一个弊端。

  1)  假设我们在DOM元素中添加了一个属性,这个属性指向了某个js对象。 dom1.ele = jsObj
  2)  当这个js对象发挥完作用后,我们已经用不到他了。这时候按理说应该把这个js变量清空,释放内存。大家都知道,如果一个js对象不存在任何外在引用的话,解释器会自动将其在内存中删除,这也是javascript相对于c++等手动管理内存的程序的优点。
  3)  但是这时候问题来了,因为DOM元素引用了这个js对象,尽管这个js对象已经没有存在的意义了,但是解释器是不会把他删除的。如果想要把其删除,我们可能需要将DOM元素的这个属性设置为null。
  4)  我们编写了这么多的代码,哪里能把 每个js对象是不是被DOM元素引用了都记住啊?
  5)  而且,假如DOM元素与js对象之间相互循环引用,根本就无法删除! 这就是内存泄漏
  6)  所以,为了避免这种情况的发生,我们要尽量避免 引用数据(这里的引用数据可以说是javascript对象) 直接依附在DOM对象上。
  7)  data就是用来搞定以上问题的方法。

data是如何搞定以上问题的?

jQuery中Data实现的大体思路:

  1)  首先我们创建一个数据缓存池,这个缓存池专门用来存储  向 DOM对象或者jQuery对象附加的额外数据。
  2)  当我们要向DOM对象或者jQuery对象附加额外数据的时候,我们附加的数据其实是保存于这个缓存池中
  3)  DOM对象或者jQuery对象生成一个额外属性,这个属性保存了 附加数据在缓存池中的‘门牌号’(位置或者索引)
  4)  当我们访问DOM对象或者jQuery对象的附加数据时,实际上是先取得其附加数据的门牌号,然后找到缓存池中对应门牌号的数据,进行操作。

(8) 获取和设置元素的位置高度


介绍这个之前先介绍一些基本信息吧。

a. 文档坐标和视口坐标

文档坐标: 就是整个相对于document的坐标位置
视口坐标: 文档内容在整个浏览器视口的相对位置。当浏览器存在scroll的时候,就可以看到而这之间的区别。

看一个例子:
  
	
	
		
	
	
		

Test Css function in jQuery

This is second div

bottpm

请看图示:




clientHeight:不包括body元素边框的内容可视区域的高度,body元素的上边框一下(不包括边框)到下边框的距离(不包括边框),从图中也可以看到。

offsetWidth: 内容可视区域的高度。真正意义上的内容区域高度。从图中可以看到这个值得计算将边框的距离计算在内了。

scrollHeight:网页正文全文高度, chorme中等于offsetWidth,但是在fireox & IE 等于clientHeight。

scrollTop:位于对象最顶端和窗口中可见内容的最顶端之间的距离,简单地说就是滚动后被隐藏的高度。由于这里没有去移动滚动条,所以是0.

screenTop:chrome,firefox,safari,opera四个都是整个浏览器相对于主显示器屏幕的位置,只有IE是文档区相对于主显示器屏幕的位置,所以大家看到的IE中有个108px在里面。请看图示:或者大家可以用红绿小工具去测试一下。


jQuery_第4张图片


height: 返回当前屏幕高度(分辨率值),这个地方执行的screen.height,是我写的时候写错了。大家可以看到三个浏览器的结果一致的。

availHeight:返回当前屏幕宽度(空白空间),这个地方的值是728,这个值是从屏幕的上端到下方工具栏上端的距离,如果你的工具栏是隐藏的或者是方法右侧的,那么这份值就是屏幕的高度。

$('body').height(): jquery中的取值是clientHeight。

b. 元素的高度和宽度

首先,任何情况下margin都不包含在height和width内。而padding与边框是否包含则有两种情况。
第一种情况:在标准盒子模型中
标准盒子模型中,宽高度值得是内容框的宽高。
IE5.5及更早的版本使用的是IE盒模型。IE6及更新的版本在标准兼容模式下使用的是W3C标准盒模型。只要为文档设置一个DOCTYPE,就会使得IE遵循标准兼容模式的方式工作。此盒模型问题只会出现在IE5.5及其更早的版本中。


第二种情况:CSS3里有一个属性box-sizing=content-box|border-box|inherit;

请看解释:


jQuery_第5张图片


c. 获取和设置元素的位置高度

getBoundingClientRect

js中的getBoundingClientRect用于获取某个元素相对于视窗的位置集合。集合中有top, right, bottom, left等属性

rectObject.top:元素上边到视窗上边的距离;
rectObject.right:元素右边到视窗左边的距离;
rectObject.bottom:元素下边到视窗上边的距离;
rectObject.left:元素左边到视窗左边的距离;

offset
jQuery中offset()方法用于获取或者设置元素的位置,该方法相对文档坐标来计算位置值,返回一个对象,带有left和top属性。
position
jQuery中的position()方法很像offset方法,但是这个方法只能用作setter,返回的元素位置都是相对偏移父元素的。
width/height
jQuery中width()/height方法返回基本的宽度和高度.
innerWidth()/innerHeight()返回元素的内容高度加上padding的高度,不加border的高度

outerWidth()和outerHeight()返回的高度是内容,padding,以及border高度之和。


3. 修改文档结构

(1) 插入和替换元素




(2) 复制元素

jQuery中的clone()方法会复制元素的一个副本(包含子孙).返回的jquery对象还不是一个文档的一部分,可以通过上一小结中的方法将其插入文档中。
clone不会复制事件处理程序和元素关联的其他数据(data),如果想要复制额外的数据,传入true参数。

(3)包装元素

wrap() 方法把每个被选元素放置在指定的 HTML 内容或元素中。
wrapAll() 在指定的 HTML 内容或元素中放置所有被选的元素。
wrapInner() 方法使用指定的 HTML 内容或元素,来包裹每个被选元素中的所有内容 (inner HTML)。

举例:

wrap():


jQuery_第6张图片

wrapAll():
jQuery_第7张图片

相信大家可以看到这个方法将所有的p标签移动到了一起,并且div.bootom-div的高度产生了变化,这其实对我们来说不是一个好事,影响了布局。

wrapInner()

jQuery_第8张图片
jQuery_第9张图片
Note:这个方法不仅可以使用字符串作为参数,也可以使用元素 / 函数作为参数。

(4) 删除元素

empty() - 从被选元素中删除子元素

$("#div1").empty();

remove() - 删除被选元素(及其子元素)
$("#div1").remove();

Note: 
不带参数的时候,会移除所有jQuery对象中的元素,传入参数的话,该参数会当做选择器,然后移除匹配选择器的元素
remove()方法会移除所有事件处理程序以及可能绑定到被移除元素上的其他数据。

detach() 方法移除被选元素,包括所有文本和子节点。
这个方法会保留 jQuery 对象中的匹配的元素,因而可以在将来再使用这些匹配的元素。
detach() 会保留所有绑定的事件、附加的数据,这一点与 remove() 不同。

unwrap:
unwrap() 方法删除被选元素的父元素。不可以传入参数,是wrap相关方法的反操作。

4. 使用jQuery处理事件


(1) 事件处理的简单注册


                                jQuery_第10张图片
例如,给单击事件注册一个事件处理程序:
$('div').click(function() {
	$(this).css("background-color", "gray");
})


Note:
a. focus和blur事件不支持冒泡。
一般都无法直接获得焦点,对于像div的元素我们可以通过两种方式获取焦点
contenteditable="true"
tabindex = -1

b. mouseover和mouseout支持事件冒泡.
但是这种冒泡的方式不太方便,因为鼠标很难知道从自己感兴趣的元素中移开了,还是从钙元素的子元素中移开了。

c. mouseenter和mouseleave非冒泡事件
这个事件可以解决b中提到的问题。

d. hover
hover()方法用给mouseenter和mouseleave事件注册处理程序。调用hover(f, g)就和调用mouseenter(f)然后调用mouseleave(g)一样,如果只传入一个参数给hover(),该参数函数会同事用作enter和leave事件的处理程序。

e. toggle
特殊的时间注册方法是toggle()。该方法将事件处理程序绑定到单击事件。可以指定两个或者多个处理程序函数。
toggle(f, g, h): 第一次点击,会调用函数f(),第二次当调用g(),第三次调用h(),第一次有再次调用f()。

但是这个方法 1.8以上被淘汰。现在用toggle只能用于隐藏和显示元素。后面会介绍。
替代方法:
var state=0;

$(".one .top").click(function() {
    if(state==0){
         
         state=1;
    }else  {
         
         state=0;
    }

});

(2) jQuery事件处理程序


jQuery事件处理程序注册函数的返回值始终有意义。如果处理程序返回false,那么改时间的默认行为以及冒泡都会被取消。相当于调用Event的preventDefault和stopPropagation方法。

result属性用于返回本次事件触发执行的上一个事件处理函数的返回值。如果为DOM元素的同一事件类型绑定了多个事件处理函数,你可以使用result属性获取上一个事件处理函数执行的返回值。

例如,你为DOM元素的"click"事件按照顺序绑定了A、B、C三个事件处理函数,你可以在事件处理函数B中获取A的返回值,在C中获取B的返回值。

该属性属于jQuery的Event对象(实例)。请看下面示例:


jQuery_第11张图片


(3) jQuery事件对象


jQuery_第12张图片

(4) 事件处理程序的高级注册


a. trigger / triggerHandler

事件的触发,用户的点击以及事件触发器trigger / triggerHandler
$('div.trigger').click(function(event){
    console.log("click event1");
})


$('div.trigger').triggerHandler('click');
trigger和triggerhandler二者之间的不同

1) trigger会触发事件冒泡,而triggerHandler则不会


jQuery_第13张图片

2) triggerHandler只触发jQuery对象集合中第一个元素的事件处理函数,而trigger则触发集合中所有对象的事件处理函数。


jQuery_第14张图片


简单解释一下输出的结果:
triggerHandler: 触发的是第一元素,对于$('div')元素集合的第一个元素是div1,所以输出的结果是div1
trigger:回和triggerHandler一样先触发div1,然后触发div2,最后又输出一个div1,相信大家已经知道为什么了。

3) trigger会触发事件的默认行为,triggerHandler则会阻止事件的默认行为。
这个地方需要换一个例子了:
  
  

$("input[type=button]").click(function() {
        $("input[type=button]").not(this).css("background-color", "white");
        $(this).css("background-color", "red");
})

$("#btn-trigger").click(function(event){  
    $("#text1").trigger("focus");  
});  
  
$("#btn-triggerHandler").click(function(event){  
    $("#text2").triggerHandler("focus");  
});  

最后看一下效果:


jQuery_第15张图片

点击trigger按钮,input输入框会获取焦点,边框高亮,变成了可以输入的状态;而点击triggerHandler按钮,input输入框没有任何反应,因为focus事件的默认行为被阻止了。

Note: 由于浏览器中链接的安全性限制,jQuery对链接的默认行为都统一为不触发,所以trigger不能触发a 标签的默认行为。

4) trigger和triggerHandler函数的返回值不同

我们接着使用3)的例子修改一下代码输出一下各自的返回值:




从上图中可以可以看到trigger返回的是jquery对象,而triggerHandler()方法会返回当前事件执行的返回值,如果没有返回值,则返回undefined。这也就有着一个新的不同,那就是trigger之后可以继续链式编程,而triggerHandler则不可以。本人测试过的。

5) isTrigger
// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
event.isTrigger = onlyHandlers ? 2 : 3;

对于响应的处理函数时,我们可以通过isTrigger判断是不是用户点击还是通过trigger(3)/triggerHandler(2)触发的。如果是用户点击则这个是是undefined。


trigger和triggerhandler传参数
$('#div1').click(function(event, triggleType, triggerName){
    console.log(triggleType + triggerName);
})

$('#div1').triggerHandler('click', ["triggerHandler","小弟"]);

console.log('-----------------------------------------')

$('#div1').trigger('click', ["trigger", "大哥"]);
输出结果就不贴出来了,需要注意的是如果传入的只是一个参数,不需要使用数组的形式。但是在响应的函数里,为什么使用triggleType, triggerName两个参数接受。因为jQuery的实现是使用apply最后去调用事件来执行函数,其实这样无可厚非,因为如果是call的方式的话,那么具体几个参数值确定不了,那么jQuery的源码又怎么去写代码!而现在的这种方式,trigger只有一个参数,那么jquery中会很好去控制,只需要检测参数的类型是不是数组。

b. bind

向匹配元素添加一个或多个事件处理器。
bind用法
jQuery_第16张图片

$('#div1').bind("customerBind", [1, 2] ,function(event, data1, data2){
    console.log(data1 + ',' + data2);
    console.log(event.data);
})

$('#div1').triggerHandler('customerBind', ["triggerHandler","小弟"]);
如果注册的是之前提到的事件处理程序简单注册的事件,可以通过用户的行为触发,如果注册类似本例子的,则需要通过trigger进行触发。

bind特性
注册多个事件
$('a').bind('mouseenter mouseleave', function() {});

允许为注册的事件处理程序指定命名空间
$('a').bind('mouseenter.myMod', function() {})

传入对象为第一个参数
$('a').bind(
    {
        mouseenter: function() {


        },
        mouseleave: function() {
            
        }
    },
    data
)

bind注销
先看一个例子:
$('#div1').bind("click", [1, 2] ,function(event, data1, data2){
    console.log(data1 + ',' + data2);
    console.log(event.data);
})

$("#div1").click(function() {
    console.log("The event is created by click");
})

$("#div1")[0].addEventListener("click", function() {
    console.log("The event is created by addEventListener");
})

$('#div1').unbind();

$('#div1').triggerHandler('click', ["triggerHandler","小弟"]);

看一下结果:




图中的结果是页面加载以及click一次div1产生的结果:红色框内的结果是triggerHandler产生的,绿色框内的是click div1产生的结果。

我们分析一下:
首先trigger当前能够触发的是:onclick属性注册的处理函数。
click div触发的是:onclick属性注册的处理函数以及addEventListener注册的处理函数。

Summary
unbind可以注销 bind注册的处理函数 | click基本事件注册的处理函数
unbind注销不了通过onclick属性注册的处理函数以及addEventListener注册的处理函数
triggerHandler不能够触发通过addEventListener注册的处理函数。

bind须知
使用.bind()不具备动态绑定功能
根据官网解释,自从jquery1.7版本以后bind()函数推荐用on()来代替。
注册多个同名的时间处理函数时,最好加上命名空间,不然当你注销函数时,会有点麻烦。

写一个例子
function eventHandler(event, data1, data2){
    console.log('事件处理具名函数eventHandler');
}

$('#div1').bind("click", function(event, data1, data2){
    console.log("事件处理匿名函数function(event, data1, data2)");
})

$('#div1').bind("click", function(event, data1){
    console.log("事件处理匿名函数function(event, data1)");
})

$('#div1').bind("click", [1, 2], eventHandler)

$('#div1').unbind('click', function(event, data1, data2){
    console.log(data1 + ',' + data2);
    console.log(event.data);
});

$('#div1').unbind('click', eventHandler);

$('#div1').triggerHandler('click', ["triggerHandler","小弟"]);

看一下结果:




结论是如果你的注册处理函数时具名函数可以通过$('#div1').unbind('click', eventHandler);注销,如果是匿名函数,很高兴的通知你,你已经无法区分了(本人现在了解到的,如果有知道的可以说明一下)。

c. live


live() / die() 1.9以上被淘汰。 替代函数:on() / off()
on对live的实现会在后面on的部分提到。

d. delegate


delegate() / undelegate() jquery1.4.2及其以上版本;

e. on

on / off jquery1.7及其以上版本;jquery1.7版本出现之后用于替代bind(),live()绑定事件方式;
用法一:$(selector).on(event,childselector,data,function)
event:必需项;添加到元素的一个或多个事件,例如 click,dblclick等;
      单事件处理:例如 $(selector).on("click",childselector,data,function);
      多事件处理:1.利用空格分隔多事件,例如 $(selector).on("click dbclick mouseout",childseletor,data,function);
            2.利用大括号灵活定义多事件,例如 $(selector).on({event1:function, event2:function, ...},childselector); 
            3.空格相隔方式:绑定较为死板,不能给事件单独绑定函数,适合处理多个事件调用同一函数情况;
               大括号替代方式:绑定较为灵活,可以给事件单独绑定函数; 
  childSelector: 可选;需要添加事件处理程序的元素,一般为selector的子元素,省略的话则直接操作在selector元素上;    
  data:可选;需要传递的参数;
  function:必需;当绑定事件发生时,需要执行的函数;
用法二:jQueryObject.on(eventsMap, selector, data)
function clickFromMap() {
    console.log("click from map");
}

function mouseoverFromMap() {
    console.log("mouseover from map")
};

$(document).on(
    {
        "click": clickFromMap, 
        "mouseover": mouseoverFromMap
    }, 
    "#div2" 
);

f. on / delegate实现的原理以及与live之间相比较的优点

$(document).delegate("#div2", "click", function(event, data1, data2){
    console.log("delegate事件处理函数:" + data1 + data2);
})

$(document).on("click", "#div2", function(event, data1, data2){
    console.log("on事件处理函数:" + data1 + data2);
})

$("#div2").click(function() {
    console.log("#div2.click");
})

$("#div1").click(function() {
    console.log("#div1.click");
})

$('#div2').triggerHandler('click', ["triggerHandler","小弟"]);

$('#div2').trigger('click', ["trigger","大哥"]);

看一下最后的输出结果


jQuery_第17张图片

首先是triggerHandler触发,由于阻止了事件冒泡,所以#div和document上注册的click事件没有触发,但是使用on,delegate注册在#div2上的click事件也没有触发。这是为什么呢?

然后再看一下trigger触发的效果,对于#div2.click, #div1.click, document.click相信大家都没有异议,有问题的是on, delegate注册的事件处理函数是在事件冒泡到document上的时候才触发的。这是一种事件委托的方法,就是把事件的响应委托给了document对象。

请看下面的图示:



从图中大家可以看到jquery.event中有一个delegateTarget属性,一个指向了document,一个指向了#div2,这种将事件委托给document的方式就是live的工作方式,因为在live、的使用方法里没有on、delegate的selector的存在,默认将事件委托给了document。而on / delegate中可以将document的范围缩小化,最大可能的减少DOM树的深层遍历,这也是live的效率慢的原因。

对于事件委托举个例子:
也是工作中的事情:例如,在我当前的项目组里,我的领导与客户交流的时候/发送email的话,可以直接自己去处理相应的事情,但是作为小弟的我就只能先通知领导说需要向客户了解一些事情需要领导帮我发一下邮件,然后将一些需要沟通的内容发送给我的领导,然后在由领导check,在发送给客户。这样就是,我将发送email给客户的事情委托给了我的leader。

我           -> 当前元素
领导           -> document
发email给客户   -> 响应函数
通知领导说需要向客户了解一些事情需要领导帮我发一下邮件 -> 事件委托
将一些需要沟通的内容发送给我的领导 -> 事件冒泡

可能着例子不太恰当,大家试着了解一下。

g on / delegate 之间的区别

第一个区别在于用法上,函数签名不同。
第二个对于childSelector一个是可选的参数,一个是必选的参数,如果delegate想要将事件委托给自己(其实就是绑定)的话,可以传入this。可能存在其他的方式,但是我没有去试。

个人建议统一使用on处理。如果对于已经存在的元素,首选基本事件处理程序注册。

5. 动画效果


(1) 动画效果的特性

每段动画都有时长,用来指定动画效果持续多长时间。

动画效果的默认时长400ms (normal), "fast"表示200ms, "slow"表示600ms。

我们可以通过jQuery.fx.speeds["customer-duration"]来设置新的时长名字,然后在动画调用的时候直接使用对应的时长名。
jQuery.fx.speeds["medium-fast"] = 300;

禁用动画

jQuery.fx.off = true; 默认值为undefined

动画的执行是异步的


(2)简单动画


a. fadeIn(), fadeOut(), fadeTo()

fadeIn()
方法通过淡入的方式显示匹配元素(没有参数时,持续时间默认为400毫秒)


fadeIn([duration])
可以接受一个持续时间参数
持续时间是以毫秒为单位的,数值越大,动画越慢。默认值为'normal',代码400毫秒的延时;'fast'和'slow'分别代表200和600毫秒的延时

fadeIn([duration][,easing])
可以接受一个可选参数easing,表示过渡使用哪种缓动函数。jQuery自身提供"linear"和"swing",默认值为swing
图中的匀速前进值得是linear,另外一条的是swing,具体的缓动函数可以查询https://j11y.io/demos/jquery/easing/

fadeIn([duration][,easing][,callback])
可以接受第三个参数,该参数也是可选参数,该参数是回调函数,表示动画完成时执行的函数

fadeOut()与fadeIn()正好相反,用来隐藏匹配元素,用法和fadeIn相同。
fadeTo()通过匹配的元素的不透明度动画,来显示或隐藏它们,用法和上面相同。

b. show(), hiddle(), toggle()

show()方法用于显示元素,与hide()方法用途正好相反,但用法相似
[注意]如果选择的元素是可见的,这个方法将不会改变任何东西

hiddle()
hide()方法是隐藏元素的最简单方法。如果没有参数,匹配的元素将被立即隐藏,没有动画。这大致相当于调用.css('display', 'none')

show()与hide()是一对互斥的方法。需要对元素进行显示隐藏的互斥切换,通常情况是需要先判断元素的display状态,然后调用其对应的处理方法。比如显示的元素,那么就要调用hide,反之亦然。 对于这样的操作行为,jQuery提供了一个便捷方法toggle()用于切换显示或隐藏匹配元素

这三个函数和a中的fadeIn()中的参数一样。

c. slideDown(), slideUp(), slideToggle()

slideDown()方法使元素由上到下延伸显示
slideUp()方法将元素由下到上缩短隐藏
slideDown与slideUp是一对相反的方法。需要对元素进行上下拉卷效果的切换,jQuery提供了一个便捷方法slideToggle()用滑动动画显示或隐藏一个匹配元素.
这三个函数和a中的fadeIn()中的参数一样。

(3)自定义动画

jQuery_第18张图片


(4)动画的取消、延迟和队列

a. 动画取消stop()

jQuery_第19张图片

第一个参数的默认值为false,等待执行的动画不会被取消,如果设置为true,会清除元素上的动画队列。

第二个参数用来指定正在连续变化的CSS属性是否保留当前值,还是变化到最终目标值。默认值为false,会保持为当前值。


b. 动画延时delay()

jQueryObject.delay( duration [, queueName ] )
duration 可选/String/Number类型指定延迟多少时间(毫秒数),默认值为400。该参数也可以为字符串"fast"(=200)或"slow"(=600)。
queueName 可选/String类型指定的队列名称,默认为"fx",表示jQuery标准的效果队列。

c. 队列

queue和dequeue是一组很有用的方法,他们对于一系列需要按次序运行的函数特别有用
queue
队列允许一个元素来异步的访问一连串的动作,而不终止程序执行。
queue    将函数加入、插入匹配元素的队列
dequeue  执行匹配元素的队列

queue( [ queueName ], newQueue )
queueName一个含有队列名的字符串。默认是"Fx",标准的动画队列。
newQueue一个替换当前函数列队内容的数组。

queue( [ queueName ], callback( next ) )
queueName一个含有队列名的字符串。默认是fx,标准的动画队列。
callback( next )添加到列队的新函数。

所以:当只传入一个参数时, 它返回并指向第一个匹配元素的队列(将是一个函数数组,队列名默认是fx); 当有两个参数传入时, 第一个参数还是默认为fx的的队列名, 第二个参数又分两种情况, 当第二个参数是一个函数时, 它将在匹配的元素的队列最后添加一个函数. 当第二个参数是一个函数数组时,它将匹配元素的队列用新的一个队列来代替(函数数组).


1. 当只传入一个参数时, 它返回并指向第一个匹配元素的队列(这是一个函数数组,队列名默认是fx的队列)
2.当传入两个参数时, 第一个参数为队列名(默认fx),当第二个参数是一个函数时, 它将在匹配的元素的队列最后添加一个函数。
当第二个参数是一个函数数组时,它将匹配元素的队列用新的一个队列来代替(函数数组)。
dequeue(queueName)
为匹配元素执行序列中的下一个函数。
clearQueue(queueName)
方法从序列中删除仍未运行的所有项目
var div = $("div");  

var FUNC=[  
function animation1() {
// 第1个动画:显示出来  
        div.show("slow"); 
        },  
function animation2() {
// 第2个动画:自动动画,水平左移300px  
        div.animate({left:'+=300'},2000);  
},  
function animation3() {
// 第3个动画:卷起来  
        div.slideToggle(1000);
}
];  

console.log("将函数数组放入自定义名为myAnimation的队列中:");
div.queue("myAnimation",FUNC);  
console.log("函数队列:" + div.queue("myAnimation"))

console.log("------------------------------------------------");
console.log("myAnimation的队列添加新的函数:");
div.queue("myAnimation", function animation4(){
alert("动画结束"); 
})
console.log("函数队列:" + div.queue("myAnimation"))

console.log("------------------------------------------------");

console.log("执行函数队列的第一个函数:")
div.dequeue("myAnimation");   
console.log("函数队列: " + div.queue("myAnimation"))

console.log("------------------------------------------------");
console.log("清除函数队列没有执行的函数:")
div.clearQueue("myAnimation");   
console.log("函数队列: " + div.queue("myAnimation"))

看一下结果:


jQuery_第20张图片

再看另外一个例子:
div
.show("slow")
.animate({left:'+=300'},2000)
.queue(
	function animation3(next) {
		div.slideToggle(1000, function() {
			console.log("second function");
		});

		//div.dequeue();
		next();
})
.slideToggle(1000, function(){
	console.log("completed");
});
这个例子我在中间加了一段queue(),如果这个function里面没有next或者dequeue的话,那么动画队列第三个和第四个函数不会执行。而且对于next的话需要加上next参数传进来。

对于jquery的内容就先写到这里吧,其实还有其他的内容,由于时间的问题就先了解这么多吧。

你可能感兴趣的:(JavaScript)