zoukankan      html  css  js  c++  java
  • jQuery

    在制作这套课程的时候,我们最新的中文版的 API 文档是 1.8 版本的,有在线和离线两
    种手段查阅:
    1.在线的可以访问:http://t.mb5u.com/jquery/
    2.离线的 AP 文档将打包提供给大家
    3.如果要看最新的文档,英文版的:http://api.jquery.com/ 看不懂可以打开谷歌翻译,虽
    然不是特别准

    使用的调试工具:Firefox 下的 firebug
    //单击按钮弹窗
    $(function () {
    $('input').click(function () {
    alert('第一个 jQuery 程序!');
    });
    });

    一. 代码风格
    在jQuery程序中,不管是页面元素的选择、内置的功能函数,都是美元符号“$”来起
    始的。而这个“$”就是jQuery当中最重要且独有的对象:jQuery对象,所以我们在页面元
    素选择或执行功能函数的时候可以这么写:

    $(function () {}); //执行一个匿名函数
    $(‘#box’); //进行执行的ID元素选择
    $(‘#box’).css(‘color’, ‘red’); //执行功能函数
    

      

    由于$本身就是jQuery对象的缩写形式,那么也就是说上面的三段代码也可以写成如下
    形式:

    jQuery(function () {});
    jQuery(‘#box’);
    jQuery(‘#box’).css(‘color’, ‘red’);
    

      

    在执行功能函数的时候,我们发现.css()这个功能函数并不是直接被“$”或jQuery对象调
    用执行的,而是先获取元素后,返回某个对象再调用.css()这个功能函数。那么也就是说,
    这个返回的对象其实也就是jQuery对象

    $().css(‘color’, ’red’); //理论上合法,但实际上缺少元素而报错
    

      

    值得一提的是,执行了.css()这个功能函数后,最终返回的还是jQuery对象,那么也就
    是说,jQuery的代码模式是采用的连缀方式,可以不停的连续调用功能函数。

    $('#box').css('color', 'red').css('font-size', '50px'); //连缀
    

      

    jQuery中代码注释和JavaScript是保持一致的,有两种最常用的注释:单行使用“//...”,
    多行使用“/* ... */”。

    //$('#box').css('color', 'red');

    二. 加载模式
    我们在之前的代码一直在使用$(function () {});这段代码进行首尾包裹,那么为什么必须
    要包裹这段代码呢?原因是我们jQuery库文件是在body元素之前加载的,我们必须等待所
    有的DOM元素加载后,延迟支持DOM操作,否则就无法获取到。
    在延迟等待加载,JavaScript提供了一个事件为load,方法如下:
    window.onload = function () {}; //JavaScript等待加载
    $(document).ready(function () {}); //jQuery等待加载

    load和ready区别

    三. 对象互换
    jQuery 对象虽然是 jQuery 库独有的对象,但它也是通过 JavaScript 进行封装而来的。我
    们可以直接输出来得到它的信息。
    alert($); //jQuery 对象方法内部
    alert($()); //jQuery 对象返回的对象,还是 jQuery
    alert($('#box')); //包裹 ID 元素返回对象,还是 jQuery
    从上面三组代码我们发现:只要使用了包裹后,最终返回的都是 jQuery 对象。这样的
    好处显而易见,就是可以连缀处理。但有时,我们也需要返回原生的 DOM 对象,比如:
    alert(document.getElementById('box')); //[object HTMLDivElement]
    jQuery 想要达到获取原生的 DOM 对象,可以这么处理:
    alert($('#box').get(0)); //ID 元素的第一个原生 DOM
    从上面 get(0),这里的索引看出,jQuery 是可以进行批量处理 DOM 的,这样可以在很
    多需要循环遍历的处理上更加得心应手。
    四.多个库之间的冲突
    当一个项目中引入多个第三方库的时候,由于没有命名空间的约束(命名空间就好比同
    一个目录下的文件夹一样,名字相同就会产生冲突),库与库之间发生冲突在所难免。
    那么,既然有冲突的问题,为什么要使用多个库呢?原因是 jQuery 只不过是 DOM 操
    作为主的库,方便我们日常 Web 开发。但有时,我们的项目有更多特殊的功能需要引入其
    他的库,比如用户界面 UI 方面的库,游戏引擎方面的库等等一系列。
    而很多库,比如 prototype、还有我们 JavaScript 课程开发的 Base 库,都使用“$”作为
    基准起始符,如果想和 jQuery 共容有两种方法:
    1.将 jQuery 库在 Base 库之前引入,那么“$”的所有权就归 Base 库所有,而 jQuery 可
    以直接用 jQuery 对象调用,或者创建一个“$$”符给 jQuery 使用。
    var $$ = jQuery; //创建一个$$的 jQuery 对象
    $(function () { //这是 Base 的$
    alert($('#box').ge(0)); //这是 Base 的$
    alert($$('#box').width()); //这是 jQuery 的$$
    });
    2.如果将 jQuery 库在 Base 库之后引入,那么“$”的所有权就归 jQuery 库所有,而 Base
    库将会冲突而失去作用。这里,jQuery 提供了一个方法:
    jQuery.noConflict(); //将$符所有权剔除
    var $$ = jQuery;
    $(function () {
    alert($('#box').ge(0));
    alert($$('#box').width());
    });
    一. 简单选择器
    在使用 jQuery 选择器时,我们首先必须使用“$()”函数来包装我们的 CSS 规则。而
    CSS 规则作为参数传递到 jQuery 对象内部后,再返回包含页面中对应元素的 jQuery 对象。
    随后,我们就可以对这个获取到的 DOM 节点进行行为操作了。
    #box { //使用 ID 选择器的 CSS 规则
    color:red; //将 ID 为 box 的元素字体颜色变红
    }
    在 jQuery 选择器里,我们使用如下的方式获取同样的结果:
    $('#box').css('color', 'red'); //获取 DOM 节点对象,并添加行为
    那么除了 ID 选择器之外,还有两种基本的选择器,分别为:元素标签名和类(class):

    alert($('div').size()); //3 个
    alert($('#box').size()); //1 个,后面两个失明了
    alert($('.box').size()); //3 个
    同理,你也可以直接使用 jQuery 核心属性来操作:
    alert($('#box').length); //1 个,后面失明了
    警告:有个问题特别要注意,ID 在页面只允许出现一次,我们一般都是要求开发者要
    遵守和保持这个规则。但如果你在页面中出现三次,并且在 CSS 使用样式,那么这三个元
    素还会执行效果。但如果,你想在 jQuery 这么去做,那么就会遇到失明的问题。所以,开
    发者必须养成良好的遵守习惯,在一个页面仅使用一个 ID。
    $('#box').css('color', 'red'); //只有第一个 ID 变红,后面两个失明
    jQuery 选择器的写法与 CSS 选择器十分类似,只不过他们的功能不同。CSS 找到元素
    后添加的是单一的样式,而 jQuery 则添加的是动作行为。最重要的一点是:CSS 在添加样
    式的时候,高级选择器会对部分浏览器不兼容,而 jQuery 选择器在添加 CSS 样式的时候却
    不必为此烦恼。
    #box > p { //CSS 子选择器,IE6 不支持
    color:red;
    }
    $('#box > p').css('color','red'); //jQuery 子选择器,兼容了 IE6
    jQuery 选择器支持 CSS1、CSS2 的全部规则,支持 CSS3 部分实用的规则,同时它还有
    少量独有的规则。所以,对于已经掌握 CSS 的开发人员,学习 jQuery 选择器几乎是零成本。
    而jQuery 选择器在获取节点对象的时候不但简单,还内置了容错功能,这样避免像 JavaScript
    那样每次对节点的获取需要进行有效判断。
    $('#pox').css('color', 'red'); //不存在 ID 为 pox 的元素,也不报错
    document.getElementById('pox').style.color = 'red'; //报错了
    因为 jQuery 内部进行了判断,而原生的 DOM 节点获取方法并没有进行判断,所以导
    致了一个错误,原生方法可以这么判断解决这个问题:
    if (document.getElementById('pox')) { //先判断是否存在这个对象
    document.getElementById('pox').style.color = 'red';
    }
    那么对于缺失不存在的元素,我们使用 jQuery 调用的话,怎么去判断是否存在呢?因
    为本身返回的是 jQuery 对象,可能会导致不存在元素存在与否,都会返回 trueif ($('#pox').length > 0) { //判断元素包含数量即可
    $('#pox').css('color', 'red');
    }
    除了这种方式之外,还可以用转换为 DOM 对象的方式来判断,例如:
    if ($('#pox').get(0)) {} 或 if ($('#pox')[0]) {} //通过数组下标也可以获取 DOM 对象
    二. 进阶选择器
    在简单选择器中,我们了解了最基本的三种选择器:元素标签名、ID 和类(class)。那么
    在基础选择器外,还有一些进阶和高级的选择器方便我们更精准的选择元素

    //群组选择器
    span, em, .box { //多种选择器添加红色字体
    color:red;
    }
    $('span, em, .box').css('color', 'red'); //群组选择器 jQuery 方式
    //后代选择器
    ul li a { //层层追溯到的元素添加红色字体
    color:red;
    }
    $('ul li a').css('color', 'red'); //群组选择器 jQuery 方式
    //通配选择器
    * { //页面所有元素都添加红色字体
    color:red;
    }
    $('*').css('color', 'red'); //通配选择器
    目前介绍的六种选择器,在实际应用中,我们可以灵活的搭配,使得选择器更加的精准
    和快速:
    $('#box p, ul li *').css('color', 'red'); //组合了多种选择器
    警告:在实际使用上,通配选择器一般用的并不多,尤其是在大通配上,比如:$('*'),
    这种使用方法效率很低,影响性能,建议竟可能少用。
    还有一种选择器,可以在 ID 和类(class)中指明元素前缀,比如:
    $('div.box'); //限定必须是.box 元素获取必须是 div
    $('p#box div.side'); //同上
    类(class)有一个特殊的模式,就是同一个 DOM 节点可以声明多个类(class)。那么对于这
    种格式,我们有多 class 选择器可以使用,但要注意和 class 群组选择器的区别。
    .box.pox { //双 class 选择器,IE6 出现异常
    color:red;
    }
    $('.box.pox').css('color', 'red'); //兼容 IE6,解决了异常
    多 class 选择器是必须一个 DOM 节点同时有多个 class,用这多个 class 进行精确限定。
    而群组 class 选择器,只不过是多个 class 进行选择而已。
    $('.box, .pox').css('color', 'red'); //加了逗号,体会区别
    警告:在构造选择器时,有一个通用的优化原则:只追求必要的确定性。当选择器筛选
    越复杂,jQuery 内部的选择器引擎处理字符串的时间就越长。比如:
    $('div#box ul li a#link'); //让 jQuery 内部处理了不必要的字符串
    $('#link'); //ID 是唯一性的,准确度不变,性能提升
    三. 高级选择器
    在前面我们学习六种最常规的选择器,一般来说通过这六种选择器基本上可以解决所有
    DOM 节点对象选择的问题。但在很多特殊的元素上,比如父子关系的元素,兄弟关系的元
    素,特殊属性的元素等等。在早期 CSS 的使用上,由于 IE6 等低版本浏览器不支持,所以
    这些高级选择器的使用也不具备普遍性,但随着 jQuery 兼容,这些选择器的使用频率也越
    来越高。

    在层次选择器中,除了后代选择器之外,其他三种高级选择器是不支持 IE6 的,而 jQuery
    却是兼容 IE6 的。
    //后代选择器
    $('#box p').css('color', 'red'); //全兼容
    jQuery 为后代选择器提供了一个等价 find()方法
    $('#box').find('p').css('color', 'red'); //和后代选择器等价
    //子选择器,孙子后失明
    #box > p { //IE6 不支持
    color:red;
    }
    $('#box > p').css('color', 'red'); //兼容 IE6
    jQuery 为子选择器提供了一个等价 children()方法:
    $('#box').children('p').css('color', 'red'); //和子选择器等价
    选择器 CSS 模式 jQuery 模式 描述
    后代选择器 ul li a {} $('ul li a') 获取追溯到的多个 DOM 对象
    子选择器 div > p {} $('div p') 只获取子类节点的多个 DOM 对象
    next 选择器 div + p {} $('div + p') 只获取某节点后一个同级DOM对象
    nextAll 选择器 div ~ p {} $('div ~ p') 获取某节点后面所有同级DOM对象
    //next 选择器(下一个同级节点)
    #box + p { //IE6 不支持
    color:red;
    }
    $('#box+p').css('color', 'red'); //兼容 IE6
    jQuery 为 next 选择器提供了一个等价的方法 next():
    $('#box').next('p').css('color', 'red'); //和 next 选择器等价
    //nextAll 选择器(后面所有同级节点)
    #box ~ p { //IE6 不支持
    color:red;
    }
    $('#box ~ p').css('color', 'red'); //兼容 IE6
    jQuery 为 nextAll 选择器提供了一个等价的方法 nextAll():
    $('#box').nextAll('p').css('color', 'red'); //和 nextAll 选择器等价
    层次选择器对节点的层次都是有要求的,比如子选择器,只有子节点才可以被选择到,
    孙子节点和重孙子节点都无法选择到。next 和 nextAll 选择器,必须是同一个层次的后一个
    和后 N 个,不在同一个层次就无法选取到了。
    在 find()、next()、nextAll()和 children()这四个方法中,如果不传递参数,就相当于传递
    了“*”,即任何节点,我们不建议这么做,不但影响性能,而且由于精准度不佳可能在复杂
    的 HTML 结构时产生怪异的结果。
    $('#box').next(); //相当于$('#box').next('*');
    为了补充高级选择器的这三种模式,jQuery 还提供了更加丰富的方法来选择元素:
    $('#box').prev('p').css('color', 'red'); //同级上一个元素
    $('#box').prevAll('p').css('color', 'red'); //同级所有上面的元素
    nextUntil()和 prevUnitl()方法是选定同级的下面或上面的所有节点,选定非指定的所有
    元素,一旦遇到指定的元素就停止选定。
    $('#box').prevUntil('p').css('color', 'red'); //同级上非指定元素选定,遇到则停止
    $('#box').nextUntil('p').css('color', 'red'); //同级下非指定元素选定,遇到则停止
    siblings()方法正好集成了 prevAll()和 nextAll()两个功能的效果,及上下相邻的所有元素
    进行选定:
    $('#box').siblings('p').css('color', 'red'); //同级上下所有元素选定
    //等价于下面:
    $('#box').prevAll('p').css('color', 'red'); //同级上所有元素选定
    $('#box').nextAll('p').css('color', 'red'); //同级下所有元素选定
    警告:切不可写成“$('#box').prevAll('p').nextAll('p').css('color', 'red');”这种形式,因为
    prevAll('p')返回的是已经上方所有指定元素,然后再 nextAll('p')选定下方所有指定元素,这
    样必然出现错误。
    理论上来讲,jQuery 提供的方法 find()、next()、nextAll()和 children()运行速度要快于使
    用高级选择器。因为他们实现的算法有所不同,高级选择器是通过解析字符串来获取节点对
    象,而 jQuery 提供的方法一般都是单个选择器,是可以直接获取的。但这种快慢的差异,
    对于客户端脚本来说没有太大的实用性,并且速度的差异还要取决了浏览器和选择的元素内
    容。比如,在 IE6/7 不支持 querySelectorAll()方法,则会使用“Sizzle”引擎,速度就会慢,
    而其他浏览器则会很快。有兴趣的可以了解这个方法和这个引擎。
    选择器快慢分析:
    //这条最快,会使用原生的 getElementById、ByName、ByTagName 和 querySelectorAll()
    $('#box').find('p');
    //jQuery 会自动把这条语句转成$('#box').find('p'),这会导致一定的性能损失。它比最快
    的形式慢了 5%-10%
    $('p', '#box');
    //这条语句在 jQuery 内部,会使用$.sibling()和 javascript 的 nextSibling()方法,一个个遍
    历节点。它比最快的形式大约慢 50%
    $('#box').children('p');
    //jQuery 内部使用 Sizzle 引擎,处理各种选择器。Sizzle 引擎的选择顺序是从右到左,
    所以这条语句是先选 p,然后再一个个过滤出父元素#box,这导致它比最快的形式大约慢
    70%
    $('#box > p');
    //这条语句与上一条是同样的情况。但是,上一条只选择直接的子元素,这一条可以于
    选择多级子元素,所以它的速度更慢,大概比最快的形式慢了 77%。
    $('#box p');
    //jQuery 内部会将这条语句转成$('#box').find('p'),比最快的形式慢了 23%。
    $('p', $('#parent'));
    综上所属,最快的是 find()方法,最慢的是$('#box p')这种高级选择器。如果一开始将
    $('#box')进行赋值,那么 jQuery 就对其变量进行缓存,那么速度会进一步提高。
    var box = $('#box');
    var p = box.find('p');
    注意:我们应该推荐使用哪种方案呢?其实,使用哪种都差不多。这里,我们推荐使用
    jQuery 提供的方法。因为不但方法的速度比高级选择器运行的更快,并且它的灵活性和扩展
    性要高于高级选择器。使用“+”或“~”从字面上没有 next 和 nextAll 更加语义化,更加清
    晰,jQuery 的方法更加丰富,提供了相对的 prev 和 prevAll。毕竟 jQuery 是编程语言,需要
    能够灵活的拆分和组合选择器,而使用 CSS 模式过于死板。所以,如果 jQuery 提供了独立
    的方法来代替某些选择器的功能,我们还是推荐优先使用独立的方法。

    属性选择器也不支持 IE6,所以在 CSS 界如果要兼容低版本,那么也是非主流。但 jQuery
    却不必考虑这个问题。
    //选定这个属性的
    a[title] { //IE6 不支持
    color:red;
    }
    $('a[title]').css('color', 'red'); //兼容 IE6 了
    //选定具有这个属性=这个属性值的
    a[title=num1] { //IE6 不支持
    color:red;
    }
    $('a[title=num1]').css('color', 'red'); //兼容 IE6 了
    //选定具有这个属性且开头属性值匹配的
    a[title^=num] { //IE6 不支持
    color:red;
    }
    $('a[title=^num]').css('color', 'red'); //兼容 IE6 了
    //选定具有这个属性且等于属性值或开头属性值匹配后面跟一个“-”号
    a[title|=num] { //IE6 不支持
    color:red;
    }
    $('a[title|="num"]').css('color', 'red'); //兼容 IE6 了
    //选定具有这个属性且结尾属性值匹配的
    a[title$=num] { //IE6 不支持
    color:red;
    }
    $('a[title$=num]').css('color','red'); //兼容 IE6 了
    //选定具有这个属性且属性值不想等的
    a[title!=num1] { //不支持此 CSS 选择器
    color:red;
    }
    $('a[title!=num1]').css('color','red'); //jQuery 支持这种写法
    //选定具有这个属性且属性值是以一个空格分割的列表,其中包含属性值的
    a[title~=num] { //IE6 不支持
    color:red;
    }
    $('a[title~=num1]').css('color','red'); //兼容 IE6
    //选定具有这个属性且属性值含有一个指定字串的
    a[title*=num] { //IE6 不支持
    color:red;
    }
    $('a[title*=num]').css('color','red'); //兼容 IE6
    //选定具有多个属性且属性值匹配成功的
    a[bbb][title=num1] { //IE6 不支持
    color:red;
    }
    $('a[bbb][title=num1]').css('color','red'); 
    一. 基本过滤器
    过滤器主要通过特定的过滤规则来筛选所需的 DOM 元素,和 CSS 中的伪类的语法类
    似:使用冒号(:)开头

    $('li:first').css('background', '#ccc'); //第一个元素
    $('li:last).css('background', '#ccc'); //最后一个元素
    $('li:not(.red)).css('background', '#ccc'); //非 class 为 red 的元素
    $('li:even').css('background', '#ccc'); //索引为偶数的元素
    $('li:odd).css('background', '#ccc'); //索引为奇数的元素
    $('li:eq(2)).css('background', '#ccc'); //指定索引值的元素
    $('li:gt(2)').css('background', '#ccc'); //大于索引值的元素
    $('li:lt(2)').css('background', '#ccc'); //小于索引值的元素
    $(':header').css('background', '#ccc'); //页面所有 h1 ~ h6 元素
    注意::focus 过滤器,必须是网页初始状态的已经被激活焦点的元素才能实现元素获取。
    而不是鼠标点击或者 Tab 键盘敲击激活的。
    $('input').get(0).focus(); //先初始化激活一个元素焦点
    $(':focus').css('background', 'red'); //被焦点的元素
    jQuery 为最常用的过滤器提供了专用的方法,已达到提到性能和效率的作用:
    $('li').eq(2).css('background', '#ccc'); //元素 li 的第三个元素,负数从后开始
    $('li').first().css('background', '#ccc'); //元素 li 的第一个元素
    $('li').last().css('background', '#ccc'); //元素 li 的最后一个元素
    $('li').not('.red').css('background', '#ccc'); //元素 li 不含 class 为 red 的元素
    注意::first、:last 和 first()、last()这两组过滤器和方法在出现相同元素的时候,first 会
    实现第一个父元素的第一个子元素,last 会实现最后一个父元素的最后一个子元素。所以,
    如果需要明确是哪个父元素,需要指明:
    $('#box li:last').css('background', '#ccc'); //#box 元素的最后一个 li
    //
    $('#box li).last().css('background', '#ccc'); //同上
    二. 内容过滤器
    内容过滤器的过滤规则主要是包含的子元素或文本内容上

    //选择元素文本节点含有 ycku.com 文本的元素
    $('div:contains("ycku.com")').css('background', '#ccc');
    $('div:empty').css('background', '#ccc'); //选择空元素
    $('ul:has(.red)').css('background', '#ccc'); //选择子元素含有 class 是 red 的元素
    $(':parent').css('background', '#ccc'); //选择非空元素
    jQuery 提供了一个 has()方法来提高:has 过滤器的性能:
    $('ul').has('.red').css('background', '#ccc'); //选择子元素含有 class 是 red 的元素
    jQuery 提供了一个名称和:parent 相似的方法,但这个方法并不是选取含有子元素或文本
    的元素,而是获取当前元素的父元素,返回的是元素集合。
    $('li').parent().css('background', '#ccc'); //选择当前元素的父元素
    $('li').parents().css('background', '#ccc'); //选择当前元素的父元素及祖先元素
    $('li').parentsUntil('div').css('background', '#ccc'); //选择当前元素遇到 div 父元素停止
    三. 可见性过滤器
    可见性过滤器根据元素的可见性和不可见性来选择相应的元素

    $('p:hidden).size(); //元素 p 隐藏的元素
    $('p:visible').size(); //元素 p 显示的元素
    注意::hidden 过滤器一般是包含的内容为:CSS 样式为 display:none、input 表单类型为
    type="hidden"和 visibility:hidden 的元素。
    四. 子元素过滤器
    子元素过滤器的过滤规则是通过父元素和子元素的关系来获取相应的元素。

    $('li:first-child').css('background', '#ccc'); //每个父元素第一个 li 元素
    $('li:last-child').css('background', '#ccc'); //每个父元素最后一个 li 元素
    $('li:only-child').css('background', '#ccc'); //每个父元素只有一个 li 元素
    $('li:nth-child(odd)').css('background', '#ccc'); //每个父元素奇数 li 元素
    $('li:nth-child(even)').css('background', '#ccc'); //每个父元素偶数 li 元素
    $('li:nth-child(2)').css('background', '#ccc'); //每个父元素第三个 li 元素
    五. 其他方法
    jQuery 在选择器和过滤器上,还提供了一些常用的方法,方便我们开发时灵活使用

    $('.red').is('li'); //true,选择器,检测 class 为是否为 red
    $('.red').is($('li')); //true,jQuery 对象集合,同上
    $('.red').is($('li').eq(2)); //true,jQuery 对象单个,同上
    $('.red').is($('li').get(2)); //true,DOM 对象,同上
    $('.red').is(function () { //true,方法,同上
    return $(this).attr('title') == '列表 3'; //可以自定义各种判断
    }));
    $('li').eq(2).hasClass('red'); //和 is 一样,只不过只能传递 class
    $('li').slice(0,2).css('color', 'red'); //前三个变成红色
    注意:这个参数有多种传法和 JavaScript 的 slice 方法是一样的比如:slice(2),从第三个
    开始到最后选定;slice(2,4),第三和第四被选定;slice(0,-2),从倒数第三个位置,向前选定
    所有;slice(2,-2),前两个和末尾两个未选定。
    $("div").find("p").end().get(0); //返回 div 的原生 DOM
    $('div').contents().size(); //返回子节点(包括文本)数量
    $('li').filter('.red').css('background','#ccc'); //选择 li 的 class 为 red 的元素
    $('li').filter('.red, :first, :last').css('background','#ccc'); //增加了首尾选择
    //特殊要求函数返回
    $('li').filter(function () {
    return $(this).attr('class') == 'red' && $(this).attr('title') == '列表 3';
    }).css('background', '#ccc');
    一.DOM  简介
    由于课程是基于 JavaScript 基础上完成的,这里我们不去详细的了解 DOM 到底是什么。
    只需要知道几个基本概念:
    1.D 表示的是页面文档 Document、O 表示对象,即一组含有独立特性的数据集合、M
    表示模型,即页面上的元素节点和文本节点。
    2.DOM 有三种形式,标准 DOM、HTML DOM、CSS DOM,大部分都进行了一系列的
    封装,在 jQuery 中并不需要深刻理解它。
    3.树形结构用来表示 DOM,就非常的贴切,大部分操作都是元素节点操作,还有少部
    分是文本节点操作。
    二. 设置元素及内容
    我们通过前面所学习的各种选择器、过滤器来得到我们想要操作的元素。这个时候,我
    们就可以对这些元素进行 DOM 的操作。那么,最常用的操作就是对元素内容的获取和修改

    在常规的 DOM 元素中,我们可以使用 html()和 text()方法获取内部的数据。html()方法
    可以获取或设置 html 内容,text()可以获取或设置文本内容。
    $('#box').html(); //获取 html 内容
    $('#box').text(); //获取文本内容,会自动清理 html 标签
    $('#box').html('<em>www.li.cc</em>'); //设置 html 内容
    $('#box').text('<em>www.li.cc</em>'); //设置文本内容,会自动转义 html 标签
    注意:当我们使用 html()或 text()设置元素里的内容时,会清空原来的数据。而我们期
    望能够追加数据的话,需要先获取原本的数据。
    $('#box').html($('#box').html() + '<em>www.li.cc</em>'); //追加数据
    如果元素是表单的话,jQuery 提供了 val()方法进行获取或设置内部的文本数据。
    $('input').val(); //获取表单内容
    $('input').val('www.li.cc'); //设置表单内容
    如果想设置多个选项的选定状态,比如下拉列表、单选复选框等等,可以通过数组传递
    操作。
    $("input").val(["check1","check2", "radio1" ]); //value 值是这些的将被选定
    三.元素属性操作
    除了对元素内容进行设置和获取,通过 jQuery 也可以对元素本身的属性进行操作,包
    括获取属性的属性值、设置属性的属性值,并且可以删除掉属性。

    $('div').attr('title'); //获取属性的属性值
    $('div').attr('title', '我是域名'); //设置属性及属性值
    $('div').attr('title', function () { //通过匿名函数返回属性值
    return '我是域名';
    });
    $('div').attr('title', function (index, value) { //可以接受两个参数
    return value + (index+1) + ',我是域名';
    });
    注意:attr()方法里的 function() {},可以不传参数。可以只传一个参数 index,表示当前
    元素的索引(从 0 开始)。也可以传递两个参数 index、value,第二个参数表示属性原本的值。
    注意:jQuery 中很多方法都可以使用 function() {}来返回出字符串,比如 html()、text()、
    val()和上一章刚学过的 is()、filter()方法。而如果又涉及到多个元素集合的话,还可以传递
    index 参数来获取索引值,并且可以使用第二个参数 value(并不是所有方法都适合,有兴趣
    可以自己逐个尝试)。
    $('div').html(function (index) { //通过匿名函数赋值,并传递 index
    return '我是' + (index+1) + '号 div';
    });
    $('div').html(function (index, value) { //还可以实现追加内容
    return '我是' + (index+1) + '号 div:'+value ;
    });
    注意:我们也可以使用 attr()来创建 id 属性,但我们强烈不建议这么做。这样会导致整
    个页面结构的混乱。当然也可以创建class 属性,但后面会有一个语义更好的方法来代替 attr()
    方法,所以也不建议使用。
    删除指定的属性,这个方法就不可以使用匿名函数,传递 index 和 value 均无效。
    $('div').removeAttr('title'); //删除指定的属性
    四. 元素样式操作
    元素样式操作包括了直接设置 CSS 样式、增加 CSS 类别、类别切换、删除类别这几种
    操作方法。而在整个 jQuery 使用频率上来看,CSS 样式的操作也是极高的,所以需要重点
    掌握。

    $('div').css('color'); //获取元素行内 CSS 样式的颜色
    $('div').css('color', 'red'); //设置元素行内 CSS 样式颜色为红色
    在 CSS 获取上,我们也可以获取多个 CSS 样式,而获取到的是一个对象数组,如果用
    传统方式进行解析需要使用 for in 遍历。
    var box = $('div').css(['color', 'height', 'width']); //得到多个 CSS 样式的原生dom数组对象
    for (var i in box) { //逐个遍历出来
    alert(i + ':' + box[i]);
    }
    jQuery 提供了一个遍历工具专门来处理这种对象数组,$.each()方法,这个方法可以轻
    松的遍历对象数组。
    $.each(box, function (attr, value) { //遍历 JavaScript 原生态的对象数组
    alert(attr + ':' + value);
    });
    使用$.each()可以遍历原生的 JavaScript 对象数组,如果是 jQuery 对象的数组怎么使
    用.each()方法呢?
    $('div').each(function (index, element) { //index 为索引,element 为元素 DOM
    alert(index + ':' + element);
    });
    在需要设置多个样式的时候,我们可以传递多个 CSS 样式的键值对即可。
    $('div').css({
    'background-color' : '#ccc',
    'color' : 'red',
    'font-size' : '20px'
    });
    如果想设置某个元素的 CSS 样式的值,但这个值需要计算我们可以传递一个匿名函数。
    $('div').css('width', function (index, value) {
    return (parseInt(value) - 500) + 'px';
    });
    除了行内 CSS 设置,我们也可以直接给元素添加 CSS 类,可以添加单个或多个,并且
    也可以删除它。
    $('div').addClass('red'); //添加一个 CSS 类
    $('div').addClass('red bg'); //添加多个 CSS 类
    $('div').removeClass('bg'); //删除一个 CSS 类
    $('div').removeClass('red bg'); //删除多个 CSS 类
    我们还可以结合事件来实现 CSS 类的样式切换功能。
    $('div').click(function () { //当点击后触发
    $(this).toggleClass('red size'); //单个样式多个样式均可
    });
    .toggleClass()方法的第二个参数可以传入一个布尔值,true表示执行切换到 class类,false
    表示执行回默认 class 类(默认的是空 class),运用这个特性,我们可以设置切换的频率。
    var count = 0;
    $('div').click(function () { //每点击两次切换一次 red
    $(this).toggleClass('red', count++ % 3 == 0);
    });
    默认的 CSS 类切换只能是无样式和指定样式之间的切换,如果想实现样式 1 和样式 2
    之间的切换还必须自己写一些逻辑。
    $('div').click(function () {
    $(this).toggleClass('red size'); //一开始切换到样式 2
    if ($(this).hasClass('red')) { //判断样式 2 存在后
    $(this).removeClass('blue'); //删除样式 1
    } else {
    $(this).toggleClass('blue'); //添加样式 1,这里也可以 addClass
    }
    });
    上面的方法较为繁琐,.toggleClass()方法提供了传递匿名函数的方式,来设置你所需要
    切换的规则。
    $('div').click(function () {
    $(this).toggleClass(function () { //传递匿名函数,返回要切换的样式
    return $(this).hasClass('red') ? 'blue' : 'red size';
    });
    });
    注意:上面虽然一句话实现了这个功能,但还是有一些小缺陷,因为原来的 class 类没
    有被删除,只不过被替代了而已。所以,需要改写一下。
    $('div').click(function () {
    $(this).toggleClass(function () {
    if ($(this).hasClass('red')) {
    $(this).removeClass('red');
    return 'green';
    } else {
    $(this).removeClass('green');
    return 'red';
    }
    });
    });
    我们也可以在传递匿名函数的模式下,增加第二个频率参数。
    var count = 0;
    $('div').click(function () {
    $(this).toggleClass(function () {
    return $(this).hasClass('red') ? 'blue' : 'red size';
    },count++ % 3 == 0); //增加了频率
    });
    对于.toggleClass()传入匿名函数的方法,还可以传递 index 索引、class 类两个参数以及
    频率布尔值,可以得到当前的索引、class 类名和频率布尔值。
    var count = 0;
    $('div').click(function () {
    $(this).toggleClass(function (index, className, switchBool) {
    alert(index + ':' + className + ':' + switchBool); //得到当前值
    return $(this).hasClass('red') ? 'blue' : 'red size';
    },count++ % 3 == 0);
    });
    五.CSS  方法
    jQuery 不但提供了 CSS 的核心操作方法,比如.css()、.addClass()等。还封装了一些特殊
    功能的 CSS 操作方法,我们分别来了解一下。

    $('div').width(); //获取元素的长度,返回的类型为 number
    $('div').width(500); //设置元素长度,直接传数值,默认加 px
    $('div').width('500pt'); //同上,设置了 pt 单位
    $('div').width(function (index, value) { //index 是索引,value 是原本值
    return value - 500; //无须调整类型,直接计算
    });

    $('div').height(); //获取元素的高度,返回的类型为 number
    $('div').height(500); //设置元素高度,直接传数值,默认加 px
    $('div').height('500pt'); //同上,设置了 pt 单位
    $('div').height(function (index, value) { //index 是索引,value 是原本值
    return value - 1; //无须调整类型,直接计算
    });

    alert($('div').width()); //不包含
    alert($('div').innerWidth()); //包含内边距 padding
    alert($('div').outerWidth()); //包含内边距 padding+边框 border
    alert($('div').outerWidth(true)); //包含内边距 padding+边框 border+外边距 margin

    $('strong').offset().left; //相对于视口的偏移
    $('strong').position().left; //相对于父元素的偏移
    $(window).scrollTop(); //获取当前滚动条的位置
    $(window).scrollTop(300); //设置当前滚动条的位置
    一. 创建节点
    为了使页面更加智能化,有时我们想动态的在 html 结构页面添加一个元素标签,那么
    在插入之前首先要做的动作就是:创建节点。
    var box = $('<div id="box">节点</div>'); //创建一个节点
    $('body').append(box); //将节点插入到<body>元素内部

    $('div').append('<strong>节点</strong>'); //向 div 内部插入 strong 节点
    $('div').append(function (index, html) { //使用匿名函数插入节点,html 是原节点
    return '<strong>节点</strong>';
    });
    $('span').appendTo('div'); //讲 span 节点移入 div 节点内
    $('span').appendTo($('div')); //同上
    $('div').prepend('<span>节点</span>'); //将 span 插入到 div 内部的前面
    $('div').append(function (index, html) { //使用匿名函数,同上
    return '<span>节点</span>';
    });
    $('span').prependTo('div'); //将 span 移入 div 内部的前面
    $('span').prependTo($('div')); //同上

    $('div').after('<span>节点</span>'); //向 div 的同级节点后面插入 span
    $('div').after(function (index, html) { //使用匿名函数,同上
    return '<span>节点</span>';
    });
    $('div').before('<span>节点</span>'); //向 div 的同级节点前面插入 span
    $('div').before(function (index, html) { //使用匿名函数,同上
    return '<span>节点</span>';
    });
    $('span').insertAfter('div'); //将 span 元素移到 div 元素外部的后面
    $('span').insertBefore('div'); //将 span 元素移到 div 元素外部的前面
    三.包裹节点
    jQuery 提供了一系列方法用于包裹节点,那包裹节点是什么意思呢?其实就是使用字符
    串代码将指定元素的代码包含着的意思。

    $('div').wrap('<strong></strong>'); //在 div 外层包裹一层 strong
    $('div').wrap('<strong>123</strong>'); //包裹的元素可以带内容
    $('div').wrap('<strong><em></em></strong>'); //包裹多个元素
    $('div').wrap($('strong').get(0)); //也可以包裹一个原生 DOM
    $('div').wrap(document.createElement('strong')); //临时的原生 DOM
    $('div').wrap(function (index) { //匿名函数
    return '<strong></strong>';
    });
    $('div').unwrap(); //移除一层包裹内容,多个需移除多次
    $('div').wrapAll('<strong></strong>'); //所有 div 外面只包一层 strong
    $('div').wrapAll($('strong').get(0)); //同上
    $('div').wrapInner('<strong></strong>'); //包裹子元素内容
    $('div').wrapInner($('strong').get(0)); //DOM 节点
    $('div').wrapInner(function () { //匿名函数
    return '<strong></strong>';
    });
    注意:.wrap()和.wrapAll()的区别在前者把每个元素当成一个独立体,分别包含一层外
    层;后者将所有元素作为一个整体作为一个独立体,只包含一层外层。这两种都是在外层包
    含,而.wrapInner()在内层包含
    四. 节点操作
    除了创建、插入和包裹节点,jQuery 还提供了一些常规的节点操作方法:复制、替换和
    删除节点。
    //复制节点
    $('body').append($('div').clone(true)); //复制一个节点添加到 HTML 中
    注意:clone(true)参数可以为空,表示只复制元素和内容,不复制事件行为。而加上 true
    参数的话,这个元素附带的事件处理行为也复制出来。
    //删除节点
    $('div').remove(); //直接删除 div 元素
    注意:.remove()不带参数时,删除前面对象选择器指定的元素。而.remove()本事也可以
    带选择符参数的,比如:$('div').remove('#box');只删除 id=box 的 div。
    //保留事件的删除节点
    $('div').detach(); //保留事件行为的删除
    注意:.remove()和.detach()都是删除节点,而删除后本身方法可以返回当前被删除的节
    点对象,但区别在于前者在恢复时不保留事件行为,后者则保留。
    //清空节点
    $('div').empty(); //删除掉节点里的内容
    //替换节点
    $('div').replaceWith('<span>节点</span>'); //将 div 替换成 span 元素
    $('<span>节点</span>').replaceAll('div'); //同上
    注意:节点被替换后,所包含的事件行为就全部消失了。
     表单选择器
    表单作为 HTML 中一种特殊的元素,操作方法较为多样性和特殊性,开发者不但可以
    使用之前的常规选择器或过滤器,也可以使用 jQuery 为表单专门提供的选择器和过滤器来
    准确的定位表单元素。
    一. 常规选择器
    我们可以使用 id、类(class)和元素名来获取表单字段,如果是表单元素,都必须含有 name
    属性,还可以结合属性选择器来精确定位。
    $('input').val(); //元素名定位,默认获取第一个
    $('input').eq(1).val(); //同上,获取第二个
    $('input[type=password]').val(); //选择 type 为 password 的字段
    $('input[name=user]').val(); //选择 name 为 user 的字段
    那么对于 id 和类(class)用法比较类似,也可以结合属性选择器来精确的定位,在这里我
    们不在重复。对于表单中的其他元素名比如:textarea、select 和 button 等,原理一样,不在
    重复。
    二. 表单选择器
    虽然可以使用常规选择器来对表单的元素进行定位,但有时还是不能满足开发者灵活多
    变的需求。所以,jQuery 为表单提供了专用的选择器。

    $(':input').size(); //获取所有表单字段元素
    $(':text).size(); //获取单行文本框元素
    $(':password').size(); //获取密码栏元素
    $(':radio).size(); //获取单选框元素
    $(':checkbox).size(); //获取复选框元素
    $(':submit).size(); //获取提交按钮元素
    $(':reset).size(); //获取重置按钮元素
    $(':image).size(); //获取图片按钮元素
    $(':file).size(); //获取文件按钮元素
    $(':button).size(); //获取普通按钮元素
    $(':hidden).size(); //获取隐藏字段元素
    注意:这些选择器都是返回元素集合,如果想获取某一个指定的元素,最好结合一下属
    性选择器。比如:
    $(':text[name=user]).size(); //获取单行文本框 name=user 的元素
    三.表单过滤器
    jQuery 提供了四种表单过滤器,分别在是否可以用、是否选定来进行表单字段的筛选过
    滤。

    $(':enabled').size(); //获取可用元素
    $(':disabled).size(); //获取不可用元素
    $(':checked).size(); //获取单选、复选框中被选中的元素
    $(':selected).size(); //获取下拉列表中被选中的元素
    一. 绑定事件
    在 JavaScript 课程的学习中,我们掌握了很多使用的事件,常用的事件有:click、dblclick、
    mousedown、mouseup、mousemove、mouseover、mouseout、change、select、submit、keydown、
    keypress、keyup、blur、focus、load、resize、scroll、error。那么,还有更多的事件可以参考
    手册中的事件部分。
    jQuery 通过.bind()方法来为元素绑定这些事件。可以传递三个参数:bind(type, [data], fn),
    type 表示一个或多个类型的事件名字符串;[data]是可选的,作为 event.data 属性值传递一个
    额外的数据,这个数据是一个字符串、一个数字、一个数组或一个对象;fn 表示绑定到指
    定元素的处理函数。
    //使用点击事件
    $('input').bind('click', function () { //点击按钮后执行匿名函数
    alert('点击!');
    });
    //普通处理函数
    $('input').bind('click', fn); //执行普通函数式无须圆括号
    function fn() {
    alert('点击!');
    }
    //可以同时绑定多个事件
    $('input').bind('mouseout mouseover', function () { //移入和移出分别执行一次
    $('div').html(function (index, value) {
    return value + '1';
    });
    });
    //通过对象键值对绑定多个参数
    $('input').bind({ //传递一个对象
    'mouseout' : function () { //事件名的引号可以省略
    alert('移出');
    },
    'mouseover' : function () {
    alert('移入');
    }
    });
    //使用 unbind 删除绑定的事件
    $('input').unbind(); //删除所有当前元素的事件
    //使用 unbind 参数删除指定类型事件
    $('input').unbind('click'); //删除当前元素的 click 事件
    //使用 unbind 参数删除指定处理函数的事件
    function fn1() {
    alert('点击 1');
    }
    function fn2() {
    alert('点击 2');
    }
    $('input').bind('click', fn1);
    $('input').bind('click', fn2);
    $('input').unbind('click', fn1); //只删除 fn1 处理函数的事件
    二. 简写事件
    为了使开发者更加方便的绑定事件,jQuery 封装了常用的事件以便节约更多的代码。我
    们称它为简写事件。

    注意:这里封装的大部分方法都比较好理解,我们没必要一一演示确认,重点看几个需
    要注意区分的简写方法。
    .mouseover()和.mouseout()表示鼠标移入和移出的时候触发。那么 jQuery 还封装了另外
    一组:.mouseenter()和.mouseleave()表示鼠标穿过和穿出的时候触发。那么这两组本质上有
    什么区别呢?手册上的说明是:.mouseenter()和.mouseleave()这组穿过子元素不会触发,
    而.mouseover()和.mouseout()则会触发。
    //HTML 页面设置
    <div style="200px;height:200px;background:green;">
    <p style="100px;height:100px;background:red;"></p>
    </div>
    <strong></strong>
    //mouseover 移入
    $('div').mouseover(function () { //移入 div 会触发,移入 p 再触发
    $('strong').html(function (index, value) {
    return value+'1';
    });
    });
    //mouseenter 穿过 移入
    $('div').mouseenter(function () { //穿过 div 或者 p
    $('strong').html(function (index, value) { //在这个区域只触发一次
    return value+'1';
    });
    });
    //mouseout 移出
    $('div').mouseout(function () { //移出 p 会触发,移出 div 再触发
    $('strong').html(function (index, value) {
    return value+'1';
    });
    });
    //mouseleave 穿出
    $('div').mouseleave(function () { //移出整个 div 区域触发一次
    $('strong').html(function (index, value) {
    return value+'1';
    });
    });
    .keydown()、.keyup()返回的是键码,而.keypress()返回的是字符编码。
    $('input').keydown(function (e) {
    alert(e.keyCode); //按下 a 返回 65
    });
    $('input').keypress(function (e) {
    alert(e.charCode); //按下 a 返回 97
    });
    注意:e.keyCode 和 e.charCode 在两种事件互换也会产生不同的效果,除了字符还有一
    些非字符键的区别。更多详情可以了解 JavaScript 事件处理那章。
    .focus()和.blur()分别表示光标激活和丢失,事件触发时机是当前元素。而.focusin()
    和.focusout()也表示光标激活和丢失,但事件触发时机可以是子元素。
    //HTML 部分
    <div style="200px;height:200px;background:red;">
    <input type="text" value="" />
    </div>
    <strong></strong>
    //focus 光标激活
    $('input').focus(function () { //当前元素触发
    $('strong').html('123');
    });
    //focusin 光标激活
    $('div').focusin(function () { //绑定的是 div 元素,子类 input 触发
    $('strong').html('123');
    });
    注意:.blur()和.focusout()表示光标丢失,和激活类似,一个必须当前元素触发,一个可
    以是子元素触发。
    三. 复合事件
    jQuery 提供了许多最常用的事件效果,组合一些功能实现了一些复合事件,比如切换功
    能、智能加载等

    //背景移入移出切换效果
    $('div').hover(function () {
    $(this).css('background', 'black'); //mouseenter 效果
    }, function () {
    $(this).css('background', 'red'); //mouseleave 效果,可省略
    });
    注意:.hover()方法是结合了.mouseenter()方法和.mouseleva()方法,并非.mouseover()
    和.mouseout()方法。
    .toggle()这个方法比较特殊,这个方法有两层含义,第一层含义就是已经被 1.8 版废用、
    1.9 版删除掉的用法,也就是点击切换复合事件的用法。第二层函数将会在动画那章讲解到。
    既然废弃掉了,就不应该使用。被删除的原因是:以减少混乱和提高潜在的模块化程度。
    但你又非常想用这个方法,并且不想自己编写类似的功能,可以下载 jquery-migrate.js
    文件,来向下兼容已被删除掉的方法。
    //背景点击切换效果(1.9 版删除掉了)
    <script type="text/javascript" src="jquery-migrate-1.2.1.js"></script>
    $('div').toggle(function () { //第一次点击切换
    $(this).css('background', 'black');
    }, function () { //第二次点击切换
    $(this).css('background', 'blue');
    }, function () { //第三次点击切换
    $(this).css('background', 'red');
    });
    注意:由于官方已经删除掉这个方法,所以也是不推荐使用的,如果在不基于向下兼容
    的插件 JS。我们可以自己实现这个功能。
    var flag = 1; //计数器
    $('div').click(function () {
    if (flag == 1) { //第一次点击
    $(this).css('background', 'black');
    flag = 2;
    } else if (flag == 2) { //第二次点击
    $(this).css('background', 'blue');
    flag = 3
    } else if (flag == 3) { //第三次点击
    $(this).css('background', 'red');
    flag = 1
    }
    });
    一.事件对象
    事件对象就是 event 对象,通过处理函数默认传递接受。之前处理函数的 e 就是 event
    事件对象,event 对象有很多可用的属性和方法,我们在 JavaScript 课程中已经详细的了解
    过这些常用的属性和方法,这里,我们再一次演示一下。
    //通过处理函数传递事件对象
    $('input').bind('click', function (e) { //接受事件对象参数
    alert(e);
    });

    //通过 event.type 属性获取触发事件名
    $('input').click(function (e) {
    alert(e.type);
    });
    //通过 event.target 获取绑定的 DOM 元素
    $('input').click(function (e) {
    alert(e.target);
    });
    //通过 event.data 获取额外数据,可以是数字、字符串、数组、对象
    $('input').bind('click', 123, function () { //传递 data 数据
    alert(e.data); //获取数字数据
    });
    注意:如果字符串就传递:'123'、如果是数组就传递:[123,'abc'],如果是对象就传递:
    {user : 'Lee', age : 100}。数组的调用方式是:e.data[1],对象的调用方式是:e.data.user。
    //event.data 获取额外数据,对于封装的简写事件也可以使用
    $('input').click({user : 'Lee', age : 100},function (e) {
    alert(e.data.user);
    });
    注意:键值对的键可以加上引号,也可以不加;在调用的时候也可以使用数组的方式:
    alert(e.data['user']);
    //获取移入到 div 之前的那个 DOM 元素
    $('div').mouseover(function (e) {
    alert(e.relatedTarget);
    });
    //获取移出 div 之后到达最近的那个 DOM 元素
    $('div').mouseout(function (e) {
    alert(e.relatedTarget);
    });
    //获取绑定的那个 DOM 元素,相当于 this,区别与 event.target
    $('div').click(function (e) {
    alert(e.currentTarget);
    });
    注意:event.target 得到的是触发元素的 DOM,event.currentTarget 得到的是监听元素的
    DOM。而 this 也是得到监听元素的 DOM。
    //获取上一次事件的返回值
    $('div').click(function (e) {
    return '123';
    });
    $('div').click(function (e) {
    alert(e.result);
    });
    //获取当前的时间戳
    $('div').click(function (e) {
    alert(e.timeStamp);
    });
    //获取鼠标的左中右键
    $('div').mousedown(function (e) {
    alert(e.which);
    });
    //获取键盘的按键
    $('input').keyup(function (e) {
    alert(e.which);
    });
    //获取是否按下了 ctrl 键,meta 键不存在,导致无法使用
    $('input').click(function (e) {
    alert(e.ctrlKey);
    });
    //获取触发元素鼠标当前的位置
    $(document).click(function (e) {
    alert(e.screenY+ ',' + e.pageY + ',' + e.clientY);
    });
    二. 冒泡和默认行为
    如果在页面中重叠了多个元素,并且重叠的这些元素都绑定了同一个事件,那么就会出
    现冒泡问题。
    //HTML 页面
    <div style="200px;height:200px;background:red;">
    <input type="button" value="按钮" />
    </div>
    //三个不同元素触发事件
    $('input').click(function () {
    alert('按钮被触发了!');
    });
    $('div').click(function () {
    alert('div 层被触发了!');
    });
    $(document).click(function () {
    alert('文档页面被触发了!');
    });
    注意:当我们点击文档的时候,只触发文档事件;当我们点击 div 层时,触发了 div 和
    文档两个;当我们点击按钮时,触发了按钮、div 和文档。触发的顺序是从小范围到大范围。
    这就是所谓的冒泡现象,一层一层往上。
    jQuery 提供了一个事件对象的方法:event.stopPropagation();这个方法设置到需要触发
    的事件上时,所有上层的冒泡行为都将被取消。
    $('input').click(function (e) {
    alert('按钮被触发了!');
    e.stopPropagation();
    });
    网页中的元素,在操作的时候会有自己的默认行为。比如:右击文本框输入区域,会弹
    出系统菜单、点击超链接会跳转到指定页面、点击提交按钮会提交数据。
    $('a').click(function (e) {
    e.preventDefault();
    });
    //禁止提交表单跳转
    $('form').submit(function (e) {
    e.preventDefault();
    });
    注意:如果想让上面的超链接同时阻止默认行为且禁止冒泡行为,可以把两个方法同时
    写上:event.stopPropagation()和 event.preventDefault()。这两个方法如果需要同时启用的时候,
    还有一种简写方案代替,就是直接 return false。
    $('a').click(function (e) {
    return false;
    });

    //判断是否取消了元素的默认行为
    $('input').keyup(function (e) {
    e.preventDefault();
    alert(e.isDefaultPrevented());
    });
    //取消冒泡并取消后续事件处理函数
    $('input').click(function (e) {
    alert('input');
    e.stopImmediatePropagation();
    });
    $('input').click(function () {
    alert('input2');
    });
    $(document).click(function () {
    alert('document');
    });
    //判断是否调用了 stopPropagation()方法
    $('input').click(function (e) {
    e.stopPropagation();
    alert(e.isPropagationStopped());
    });
    //判断是否执行了 stopImmediatePropagation()方法
    $('input').click(function (e) {
    e.stopImmediatePropagation();
    alert(e.isImmediatePropagationStopped());
    });
    jQuery 不但封装了大量常用的事件处理,还提供了不少高级事件方便开发者使用。比
    如模拟用户触发事件、事件委托事件、和统一整合的 on 和 off,以及仅执行一次的 one 方
    法。这些方法大大降低了开发者难度,提升了开发者的开发体验。
    一. 模拟操作
    在事件触发的时候,有时我们需要一些模拟用户行为的操作。例如:当网页加载完毕后
    自行点击一个按钮触发一个事件,而不是用户去点击。
    //点击按钮事件
    $('input').click(function () {
    alert('我的第一次点击来自模拟!');
    });
    //模拟用户点击行为
    $('input').trigger('click');
    //可以合并两个方法
    $('input').click(function () {
    alert('我的第一次点击来自模拟!');
    }).trigger('click');
    有时在模拟用户行为的时候,我们需要给事件执行传递参数,这个参数类似与 event.data
    的额外数据,可以可以是数字、字符串、数组、对象。
    $('input').click(function (e, data1, data2) {
    alert(data1 + ',' + data2);
    }).trigger('click', ['abc', '123']);
    注意:当传递一个值的时候,直接传递即可。当两个值以上,需要在前后用中括号包含
    起来。但不能认为是数组形式,下面给出一个复杂的说明。
    $('input').click(function (e, data1, data2) {
    alert(data1.a + ',' + data2[1]);
    }).trigger('click', [{'a' : '1', 'b' : '2'}, ['123','456']]);
    除了通过 JavaScript 事件名触发,也可以通过自定义的事件触发,所谓自定义事件其实
    就是一个被.bind()绑定的任意函数。
    $('input').bind('myEvent', function () {
    alert('自定义事件!');
    }).trigger('myEvent');
    .trigger()方法提供了简写方案,只要想让某个事件执行模拟用户行为,直接再调用一个
    空的同名事件即可。
    $('input').click(function () {
    alert('我的第一次点击来自模拟!');
    }).click(); //空的 click()执行的是 trigger()
    这种便捷的方法,jQuery 几乎个所有常用的事件都提供了。

    jQuery 还提供了另外一个模拟用户行为的方法:.triggerHandler();这个方法的使用
    和.trigger()方法一样。
    $('input').click(function () {
    alert('我的第一次点击来自模拟!');
    }).triggerHandler('click');
    在常规的使用情况下,两者几乎没有区别,都是模拟用户行为,也可以可以传递额外参
    数。但在某些特殊情况下,就产生了差异:
    1..triggerHandler()方法并不会触发事件的默认行为,而.trigger()会。
    $('form').trigger('submit'); //模拟用户执行提交,并跳转到执行页面
    $('form').triggerHandler('submit'); //模拟用户执行提交,并阻止的默认行为
    如果我们希望使用.trigger()来模拟用户提交,并且阻止事件的默认行为,则需要这么写:
    $('form').submit(function (e) {
    e.preventDefault(); //阻止默认行为
    }).trigger('submit');
    2..triggerHandler()方法只会影响第一个匹配到的元素,而.trigger()会影响所有。
    3..triggerHandler()方法会返回当前事件执行的返回值,如果没有返回值,则返回
    undefined;而.trigger()则返回当前包含事件触发元素的 jQuery 对象(方便链式连缀调用)。
    alert($('input').click(function () {
    return 123;
    }).triggerHandler('click')); //返回 123,没有 return 返回
    4..trigger()在创建事件的时候,会冒泡。但这种冒泡是自定义事件才能体现出来,是
    jQuery 扩展于 DOM 的机制,并非 DOM 特性。而.triggerHandler()不会冒泡。
    var index = 1;
    $('div').bind('myEvent',function(){
    alert('自定义事件' + index);
    index++;
    });
    $('.div3').trigger("myEvent");
    二. 命名空间
    有时,我们想对事件进行移除。但对于同名同元素绑定的事件移除往往比较麻烦,这个
    时候,可以使用事件的命名空间解决。
    $('input').bind('click.abc', function () {
    alert('abc');
    });
    $('input').bind('click.xyz', function () {
    alert('xyz');
    });
    $('input').unbind('click.abc'); //移除 click 实践中命名空间为 abc 的
    注意:也可以直接使用('.abc'),这样的话,可以移除相同命名空间的不同事件。对于模
    拟操作.trigger()和.triggerHandler(),用法也是一样的。
    $('input').trigger('click.abc');
    三. 事件委托
    什么是事件委托?用现实中的理解就是:有 100 个学生同时在某天中午收到快递,但这
    100 个学生不可能同时站在学校门口等,那么都会委托门卫去收取,然后再逐个交给学生。
    而在 jQuery 中,我们通过事件冒泡的特性,让子元素绑定的事件冒泡到父元素(或祖先元素)
    上,然后再进行相关处理即可。
    如果一个企业级应用做报表处理,表格有 2000 行,每一行都有一个按钮处理。如果用
    之前的.bind()处理,那么就需要绑定 2000 个事件,就好比 2000 个学生同时站在学校门口等
    快递,不断会堵塞路口,还会发生各种意外。这种情况放到页面上也是一样,可能导致页面
    极度变慢或直接异常。而且,2000 个按钮使用 ajax 分页的话,.bind()方法无法动态绑定尚
    未存在的元素。就好比,新转学的学生,快递员无法验证他的身份,就可能收不到快递。
    //HTML 部分
    <div style="background:red;200px;height:200px;" id="box">
    <input type="button" value="按钮" class="button" />
    </div>
    //使用.bind()不具备动态绑定功能,只有点击原始按钮才能生成
    $('.button').bind('click', function () {
    $(this).clone().appendTo('#box');
    });
    //使用.live()具备动态绑定功能,jQuery1.3 使用,jQuery1.7 之后废弃,jQuery1.9 删除
    $('.button').live('click', function () {
    $(this).clone().appendTo('#box');
    });
    .live()原理就是把 click 事件绑定到祖先元素$(document)上,而只需要给$(document)绑
    定一次即可,而非 2000 次。然后就可以处理后续动态加载的按钮的单击事件。在接受任何
    事件时,$(document)对象都会检查事件类型(event.type)和事件目标(event.target),如果 click
    事件是.button,那么就执行委托给它的处理程序。.live()方法已经被删除,无法使用了。需
    要测试使用的话,需要引入向下兼容插件。
    //.live()无法使用链接连缀调用,因为参数的特性导致
    $('#box').children(0).live('click', function () {
    $(this).clone().appendTo('#box');
    });
    在上面的例子中,我们使用了.clone()克隆。其实如果想把事件行为复制过来,我们只
    需要传递 true 即可:.clone(true)。这样也能实现类似事件委托的功能,但原理却截然不同。
    一个是复制事件行为,一个是事件委托。而在非克隆操作下,此类功能只能使用事件委托。
    $('.button').live('click', function () {
    $('<input type="button" value="复制的" class="button" />').appendTo('#box');
    });
    当我们需要停止事件委托的时候,可以使用.die()来取消掉。
    $('.button').die('click');
    由于.live()和.die()在 jQuery1.4.3 版本中废弃了,之后推出语义清晰、减少冒泡传播层次、
    又支持链接连缀调用方式的方法:.delegate()和.undelegate()。但这个方法在 jQuery1.7 版本中
    被.on()方法整合替代了。
    $('#box').delegate('.button', 'click', function () {
    $(this).clone().appendTo('#box');
    });
    $('#box').undelegate('.button','click');
    //支持连缀调用方式
    $('div').first().delegate('.button', 'click', function () {
    $(this).clone().appendTo('div:first');
    });
    注意:.delegate()需要指定父元素,然后第一个参数是当前元素,第二个参数是事件方
    式,第三个参数是执行函数。和.bind()方法一样,可以传递额外参数。.undelegate()和.unbind()
    方法一样可以直接删除所有事件,比如:.undelegate('click')。也可以删除命名空间的事件,
    比如:.undelegate('click.abc')。
    注意:.live()和.delegate()和.bind()方法一样都是事件绑定,那么区别也很明显,用途上
    遵循两个规则:1.在 DOM 中很多元素绑定相同事件时;2.在 DOM 中尚不存在即将生成的
    元素绑定事件时;我们推荐使用事件委托的绑定方式,否则推荐使用.bind()的普通绑定。
    四.on off one
    目前绑定事件和解绑的方法有三组共六个。由于这三组的共存可能会造成一定的混乱,
    为此 jQuery1.7 以后推出了.on()和.off()方法彻底摒弃前面三组。
    //替代.bind()方式
    $('.button').on('click', function () {
    alert('替代.bind()');
    });
    //替代.bind()方式,并使用额外数据和事件对象
    $('.button').on('click', {user : 'Lee'}, function (e) {
    alert('替代.bind()' + e.data.user);
    });
    //替代.bind()方式,并绑定多个事件
    $('.button').on('mouseover mouseout', function () {
    alert('替代.bind()移入移出!');
    });
    //替代.bind()方式,以对象模式绑定多个事件
    $('.button').on({
    mouseover : function () {
    alert('替代.bind()移入!');
    },
    mouseout : function () {
    alert('替代.bind()移出!');
    }
    });
    //替代.bind()方式,阻止默认行为并取消冒泡
    $('form').on('submit', function () {
    return false;
    });
    或
    $('form').on('submit', false);
    //替代.bind()方式,阻止默认行为
    $('form').on('submit', function (e) {
    e.preventDefault();
    });
    //替代.bind()方式,取消冒泡
    $('form').on('submit', function (e) {
    e.stopPropagation();
    });
    //替代.unbind()方式,移除事件
    $('.button').off('click');
    $('.button').off('click', fn);
    $('.button').off('click.abc');
    //替代.live()和.delegate(),事件委托 .button是触发的元素,#box是绑定的事件
    $('#box').on('click', '.button', function () {
    $(this).clone().appendTo('#box');
    });
    //替代.die()和.undelegate(),取消事件委托
    $('#box').off('click', '.button');
    注意:和之前方式一样,事件委托和取消事件委托也有各种搭配方式,比如额外数据、
    命名空间等等,这里不在赘述。
    不管是.bind()还是.on(),绑定事件后都不是自动移除事件的,需要通过.unbind()和.off()
    来手工移除。jQuery 提供了.one()方法,绑定元素执行完毕后自动移除事件,可以方法仅触
    发一次的事件。
    //类似于.bind()只触发一次
    $('.button').one('click', function () {
    alert('one 仅触发一次!');
    });
    //类似于.delegate()只触发一次
    $('#box).one('click', 'click', function () {
    alert('one 仅触发一次!');
    });
    在以前很长一段时间里,网页上的各种特效还需要采用 flash 在进行。但最近几年里,
    我们已经很少看到这种情况了,绝大部分已经使用 JavaScript 动画效果来取代 flash。这里
    说的取代是网页特效部分,而不是动画。网页特效比如:渐变菜单、渐进显示、图片轮播等;
    而动画比如:故事情节广告、MV 等等。
    一. 显示、隐藏
    jQuery 中显示方法为:.show(),隐藏方法为:.hide()。在无参数的时候,只是硬性的显
    示内容和隐藏内容。
    $('.show').click(function () { //显示
    $('#box').show();
    });
    $('.hide').click(function () { //隐藏
    $('#box').hide();
    });
    注意:.hide()方法其实就是在行内设置 CSS 代码:display:none; 而.show()方法要根据原
    来元素是区块还是内联来决定,如果是区块,则设置 CSS 代码:display:block; 如果是内联,
    则设置 CSS 代码:display:inline;。
    在.show()和.hide()方法可以传递一个参数,这个参数以毫秒(1000 毫秒等于 1 秒钟)来控
    制速度。并且里面富含了匀速变大变小,以及透明度变换。
    $('.show').click(function () {
    $('#box').show(1000); //显示用了 1 秒
    });
    $('.hide').click(function () {
    $('#box').hide(1000); //隐藏用了 1 秒
    });
    除了直接使用毫秒来控制速度外,jQuery 还提供了三种预设速度参数字符串:slow、
    normal 和 fast,分别对应 600 毫秒、400 毫秒和 200 毫秒。
    $('.show').click(function () {
    $('#box').show('fast'); //200 毫秒
    });
    $('.hide').click(function () {
    $('#box').hide('slow'); //600 毫秒
    });
    注意:不管是传递毫秒数还是传递预设字符串,如果不小心传递错误或者传递空字符串。
    那么它将采用默认值:400 毫秒。
    $('.show').click(function () {
    $('#box').show(''); //默认 400 毫秒
    });
    //使用.show()和.hide()的回调函数,可以实现列队动画效果。
    $('.show').click(function () {
    $('#box').show('slow', function () {
    alert('动画持续完毕后,执行我!');
    });
    });
    //列队动画,使用函数名调用自身
    $('.show').click(function () {
    $('div').first().show('fast', function showSpan() {
    $(this).next().show('fast', showSpan);
    });
    });
    //列队动画,使用 arguments.callee 匿名函数自调用
    $('.hide').click(function () {
    $('div').last().hide('fast', function() {
    $(this).prev().hide('fast', arguments.callee);
    });
    });
    我们在使用.show()和.hide()的时候,如果需要一个按钮切换操作,需要进行一些条件判
    断。而 jQuery 提供给我们一个类似功能的独立方法:.toggle()。
    $('.toggle').click(function () {
    $(this).toggle('slow');
    });
    二.滑动、卷动
    jQuery 提供了一组改变元素高度的方法:.slideUp()、.slideDown()和.slideToggle()。顾名
    思义,向上收缩(卷动)和向下展开(滑动)。
    $('.down').click(function () {
    $('#box').slideDown();
    });
    $('.up').click(function () {
    $('#box').slideUp();
    });
    $('.toggle').click(function () {
    $('#box').slideToggle();
    });
    注意:滑动、卷动效果和显示、隐藏效果一样,具有相同的参数。
    三. 淡入、淡出
    jQuery 提供了一组专门用于透明度变化的方法:.fadeIn()和.fadeOut(),分别表示淡入、
    淡出,当然还有一个自动切换的方法:.fadeToggle()。
    $('.in').click(function () {
    $('#box').fadeIn('slow');
    });
    $('.out').click(function () {
    $('#box').fadeOut('slow');
    });
    $('.toggle').click(function () {
    $('#box').fadeToggle();
    });
    上面三个透明度方法只能是从 0 到 100,或者从 100 到 0,如果我们想设置指定值就没
    有办法了。而 jQuery 为了解决这个问题提供了.fadeTo()方法。
    $('.toggle').click(function () {
    $('#box').fadeTo('slow', 0.33); //0.33 表示值为 33
    });
    注意:淡入、淡出效果和显示、隐藏效果一样,具有相同的参数。对于.fadeTo()方法,
    如果本身透明度大于指定值,会淡出,否则相反
    四. 自定义动画
    jQuery 提供了几种简单常用的固定动画方面我们使用。但有些时候,这些简单动画无法
    满足我们更加复杂的需求。这个时候,jQuery 提供了一个.animate()方法来创建我们的自定
    义动画,满足更多复杂多变的要求。
    $('.animate').click(function () {
    $('#box').animate({
    'width' : '300px',
    'height' : '200px',
    'fontSize' : '50px',
    'opacity' : 0.5
    });
    });
    注意:一个 CSS 变化就是一个动画效果,上面的例子中,已经有四个 CSS 变化,已经
    实现了多重动画同步运动的效果。
    必传的参数只有一个,就是一个键值对 CSS 变化样式的对象。还有两个可选参数分别
    为速度和回调函数。
    $('.animate').click(function () {
    $('#box').animate({
    'width' : '300px',
    'height' : '200px'
    }, 1000, function () {
    alert('动画执行完毕执行我!');
    });
    });
    到目前位置,我们都是创建的固定位置不动的动画。如果想要实现运动状态的位移动画,
    那就必须使用自定义动画,并且结合 CSS 的绝对定位功能。
    $('.animate').click(function () {
    $('#box').animate({
    'top' : '300px', //先必须设置 CSS 绝对定位
    'left' : '200px'
    });
    });
    自定义动画中,每次开始运动都必须是初始位置或初始状态,而有时我们想通过当前位
    置或状态下再进行动画。jQuery 提供了自定义动画的累加、累减功能。
    $('.animate').click(function () {
    $('#box').animate({
    'left' : '+=100px',
    });
    });
    自定义实现列队动画的方式,有两种:1.在回调函数中再执行一个动画;2.通过连缀或
    顺序来实现列队动画。
    //通过依次顺序实现列队动画
    $('.animate').click(function () {
    $('#box').animate({'left' : '100px'});
    $('#box').animate({'top' : '100px'});
    $('#box').animate({'width' : '300px'});
    });
    注意:如果不是同一个元素,就会实现同步动画
    //通过连缀实现列队动画
    $('.animate').click(function () {
    $('#box').animate({
    'left' : '100px'
    }).animate({
    'top' : '100px'
    }).animate({
    'width' : '300px'
    });
    });
    //通过回调函数实现列队动画
    $('.animate').click(function () {
    $('#box').animate({
    'left' : '100px'
    }, function () {
    $('#box').animate({
    'top' : '100px'
    }, function () {
    $('#box').animate({
    'width' : '300px'
    });
    });
    });
    });
    五. 列队动画方法
    之前我们已经可以实现列队动画了,如果是同一个元素,可以依次顺序或连缀调用。如
    果是不同元素,可以使用回调函数。但有时列队动画太多,回调函数的可读性大大降低。为
    此,jQuery 提供了一组专门用于列队动画的方法。
    //连缀无法实现按顺序列队
    $('#box').slideUp('slow').slideDown('slow').css('background', 'orange');
    注意:如果动画方法,连缀可以实依次列队,而.css()方法不是动画方法,会在一开始
    传入列队之前。那么,可以采用动画方法的回调函数来解决。
    //使用回调函数,强行将.css()方法排队到.slideDown()之后
    $('#box').slideUp('slow').slideDown('slow', function () {
    $(this).css('background', 'orange');
    });
    但如果这样的话,当列队动画繁多的时候,可读性不但下降,而原本的动画方法不够清
    晰。所以,我们的想法是每个操作都是自己独立的方法。那么 jQuery 提供了一个类似于回
    调函数的方法:.queue()。
    //使用.queue()方法模拟动画方法跟随动画方法之后
    $('#box').slideUp('slow').slideDown('slow').queue(function () {
    $(this).css('background', 'orange');
    });
    现在,我们想继续在.queue()方法后面再增加一个隐藏动画,这时发现居然无法实现。
    这是.queue()特性导致的。有两种方法可以解决这个问题,jQuery 的.queue()的回调函数可以
    传递一个参数,这个参数是 next 函数,在结尾处调用这个 next()方法即可再连缀执行列队动
    画。
    //使用 next 参数来实现继续调用列队动画
    $('#box').slideUp('slow').slideDown('slow').queue(function (next) {
    $(this).css('background', 'orange');
    next();
    }).hide('slow');
    因为next函数是jQuery1.4版本以后才出现的,而之前我们普遍使用的是.dequeue()方法。
    意思为执行下一个元素列队中的函数。
    //使用.dequeue()方法执行下一个函数动画
    $('#box').slideUp('slow').slideDown('slow').queue(function () {
    $(this).css('background', 'orange');
    $(this).dequeue();
    }).hide('slow');
    如果采用顺序调用,那么使用列队动画方法,就非常清晰了,每一段代表一个列队,而
    回调函数的嵌套就会杂乱无章。
    //使用顺序调用的列队,逐个执行,非常清晰
    $('#box').slideUp('slow');
    $('#box').slideDown('slow');
    $('#box').queue(function () {
    $(this).css('background', 'orange');
    $(this).dequeue();
    })
    $('#box').hide('slow');
    .queue()方法还有一个功能,就是可以得到当前动画个列队的长度。当然,这个用法在
    普通 Web 开发中用的比较少,我们这里不做详细探讨。
    //获取当前列队的长度,fx 是默认列队的参数
    function count() {
    return $("#box").queue('fx').length;
    }
    //在某个动画处调用
    $('#box').slideDown('slow', function () {alert(count());});
    jQuery 还提供了一个清理列队的功能方法:.clearQueue()。把它放入一个列队的回调函
    数或.queue()方法里,就可以把剩下为执行的列队给移除。
    //清理动画列队
    $('#box').slideDown('slow', function () {$(this).clearQueue()});
    六. 动画相关方法
    很多时候需要停止正在运行中的动画,jQuery 为此提供了一个.stop()方法。它有两个可
    选参数:.stop(clearQueue, gotoEnd);clearQueue 传递一个布尔值,代表是否清空未执行完的
    动画列队,gotoEnd 代表是否直接将正在执行的动画跳转到末状态。
    //强制停止运行中的
    $('.stop').click(function () {
    $('#box').stop();
    });
    //带参数的强制运行
    $('.animate').click(function () {
    $('#box').animate({
    'left' : '300px'
    }, 1000);
    $('#box').animate({
    'bottom' : '300px'
    }, 1000);
    $('#box').animate({
    'width' : '300px'
    }, 1000);
    $('#box').animate({
    'height' : '300px'
    }, 1000);
    });
    $('.stop').click(function () {
    $('#box').stop(true ,true);
    });
    注意:第一个参数表示是否取消列队动画,默认为 false。如果参数为 true,当有列队动
    画的时候,会取消后面的列队动画。第二参数表示是否到达当前动画结尾,默认为 false。
    如果参数为 true,则停止后立即到达末尾处。
    有时在执行动画或列队动画时,需要在运动之前有延迟执行,jQuery 为此提供了.delay()
    方法。这个方法可以在动画之前设置延迟,也可以在列队动画中间加上。
    //开始延迟 1 秒钟,中间延迟 1 秒
    $('.animate').click(function () {
    $('#box').delay(1000).animate({
    'left' : '300px'
    }, 1000);
    $('#box').animate({
    'bottom' : '300px'
    }, 1000);
    $('#box').delay(1000).animate({
    'width' : '300px'
    }, 1000);
    $('#box').animate({
    'height' : '300px'
    }, 1000);
    });
    在选择器的基础章节中,我们提到过一个过滤器:animated,这个过滤器可以判断出当前
    运动的动画是哪个元素。通过这个特点,我们可以避免由于用户快速在某个元素执行动画时,
    由于动画积累而导致的动画和用户的行为不一致。
    //递归执行自我,无线循环播放
    $('#box').slideToggle('slow', function () {
    $(this).slideToggle('slow', arguments.callee);
    });
    //停止正在运动的动画,并且设置红色背景
    $('.button').click(function(){
    $('div:animated').stop().css('background', 'red');
    });
    六. 动画全局属性
    jQuery 提供了两种全局设置的属性,分别为:$.fx.interval,设置每秒运行的帧数;$.fx.off,
    关闭页面上所有的动画。
    $.fx.interval 属性可以调整动画每秒的运行帧数,默认为 13 毫秒。数字越小越流畅,但
    可能影响浏览器性能。
    //设置运行帧数为 1000 毫秒
    $.fx.interval = 1000; //默认为 13
    $('.button').click(function () {
    $('#box').toggle(3000);
    });
    $.fx.off 属性可以关闭所有动画效果,在非常低端的浏览器,动画可能会出现各种异常
    问题导致错误。而 jQuery 设置这个属性,就是用于关闭动画效果的。
    //设置动画为关闭 true
    $.fx.off = true; //默认为 false
    补充:在.animate()方法中,还有一个参数,easing 运动方式,这个参数,大部分参数值
    需要通过插件来使用,在后面的课程中,会详细讲解。自带的参数有两个:swing(缓动)、
    linear(匀速),默认为 swing。
    $('.button').click(function () {
    $('#box').animate({
    left : '800px'
    }, 'slow', 'swing');
    $('#pox').animate({
    left : '800px'
    }, 'slow', 'linear');
    });
    Ajax 全称为:“Asynchronous JavaScript and XML”(异步 JavaScript 和 XML),
    它并不是 JavaScript 的一种单一技术,而是利用了一系列交互式网页应用相关的技术所形
    成的结合体。使用 Ajax,我们可以无刷新状态更新页面,并且实现异步提交,提升了用户
    体验。
    一.Ajax  概述
    Ajax 这个概念是由 Jesse James Garrett 在 2005 年发明的。它本身不是单一技术,是一串
    技术的集合,主要有:
    1.JavaScript,通过用户或其他与浏览器相关事件捕获交互行为;
    2.XMLHttpRequest 对象,通过这个对象可以在不中断其它浏览器任务的情况下向服务
    器发送请求;
    3.服务器上的文件,以 XML、HTML 或 JSON 格式保存文本数据;
    4.其它 JavaScript,解释来自服务器的数据(比如 PHP 从 MySQL 获取的数据)并将其
    呈现到页面上。
    由于 Ajax 包含众多特性,优势与不足也非常明显。优势主要以下几点:
    1.不需要插件支持(一般浏览器且默认开启 JavaScript 即可);
    2.用户体验极佳(不刷新页面即可获取可更新的数据);
    3.提升 Web 程序的性能(在传递数据方面做到按需放松,不必整体提交);
    4.减轻服务器和带宽的负担(将服务器的一些操作转移到客户端);
    而 Ajax 的不足由以下几点:
    1.不同版本的浏览器度 XMLHttpRequest 对象支持度不足(比如 IE5 之前);
    2.前进、后退的功能被破坏(因为 Ajax 永远在当前页,不会几率前后页面);
    3.搜索引擎的支持度不够(因为搜索引擎爬虫还不能理解 JS 引起变化数据的内容);
    4.开发调试工具缺乏(相对于其他语言的工具集来说,JS 或 Ajax 调试开发少的可怜)。
    异步和同步
    使用 Ajax 最关键的地方,就是实现异步请求、接受响应及执行回调。那么异步与同步
    有什么区别呢?我们普通的 Web 程序开发基本都是同步的,意为执行一段程序才能执行下
    一段,类似电话中的通话,一个电话接完才能接听下个电话;而异步可以同时执行多条任务,
    感觉有多条线路,类似于短信,不会因为看一条短信而停止接受另一条短信。Ajax 也可以
    使用同步模式执行,但同步的模式属于阻塞模式,这样会导致多条线路执行时又必须一条一
    条执行,会让 Web 页面出现假死状态,所以,一般 Ajax 大部分采用异步模式。
    二.load() 方法
    jQuery 对 Ajax 做了大量的封装,我们使用起来也较为方便,不需要去考虑浏览器兼容
    性。对于封装的方式,jQuery 采用了三层封装:最底层的封装方法为:$.ajax(),而通过这
    层封装了第二层有三种方法:.load()、$.get()和$.post(),最高层是$.getScript()和$.getJSON()
    方法。
    .load()方法可以参数三个参数:url(必须,请求 html 文件的 url 地址,参数类型为 String)、
    data(可选,发送的 key/value 数据,参数类型为 Object)、callback(可选,成功或失败的回调
    函数,参数类型为函数 Function)。
    如果想让 Ajax 异步载入一段 HTML 内容,我们只需要一个 HTML 请求的 url 即可。
    //HTML
    <input type="button" value="异步获取数据" />
    <div id="box"></div>
    //jQuery
    $('input').click(function () {
    $('#box').load('test.html');
    });
    如果想对载入的 HTML 进行筛选,那么只要在 url 参数后面跟着一个选择器即可。
    //带选择器的 url
    $('input').click(function () {
    $('#box').load('test.html .my');
    });
    如果是服务器文件,比如.php。一般不仅需要载入数据,还需要向服务器提交数据,那
    么我们就可以使用第二个可选参数 data。向服务器提交数据有两种方式:get 和 post。
    //不传递 data,则默认 get 方式
    $('input').click(function () {
    $('#box').load('test.php?url=ycku');
    });
    //get 方式接受的 PHP
    <?php
    if ($_GET['url'] == 'ycku') {
    echo '瓢城 Web 俱乐部官网';
    } else {
    echo '其他网站';
    }
    ?>
    //传递 data,则为 post 方式
    $('input').click(function () {
    $('#box').load('test.php', {
    url : 'ycku'
    });
    });
    //post 方式接受的 PHP
    <?php
    if ($_POST['url'] == 'ycku') {
    echo '瓢城 Web 俱乐部官网';
    } else {
    echo '其他网站';
    }
    ?>
    在 Ajax 数据载入完毕之后,就能执行回调函数 callback,也就是第三个参数。回调函数
    也可以传递三个可选参数:responseText (请求返回)、textStatus (请求状态)、XMLHttpRequest
    (XMLHttpRequest 对象)。
    $('input').click(function () {
    $('#box').load('test.php', {
    url : 'ycku'
    }, function (response, status, xhr) {
    alert('返回的值为:' + response + ',状态为:' + status + ',
    状态是:' + xhr.statusText);
    });
    });
    注意:status 得到的值,如果成功返回数据则为:success,否则为:error。XMLHttpRequest
    对象属于 JavaScript 范畴,可以调用一些属性如下:

    三.$.get() 和$.post()
    .load()方法是局部方法,因为他需要一个包含元素的 jQuery 对象作为前缀。而$.get()和
    $.post()是全局方法,无须指定某个元素。对于用途而言,.load()适合做静态文件的异步获取,
    而对于需要传递参数到服务器页面的,$.get()和$.post()更加合适。
    $.get()方法有四个参数,前面三个参数和.load()一样,多了一个第四参数 type,即服务
    器返回的内容格式:包括 xml、html、script、json、jsonp 和 text。第一个参数为必选参数,
    后面三个为可选参数。
    //使用$.get()异步返回 html 类型
    $('input').click(function () {
    $.get('test.php', {
    url : 'ycku'
    }, function (response, status, xhr) {
    if (status == 'success') {
    $('#box').html(response);
    }
    }) //type 自动转为 html
    });
    注意:第四参数 type 是指定异步返回的类型。一般情况下 type 参数是智能判断,并不
    需要我们主动设置,如果主动设置,则会强行按照指定类型格式返回。
    //使用$.get()异步返回 xml
    $('input').click(function () {
    $.get('test.xml', function (response, status, xhr) {
    $('#box').html($(response).find('root').find('url').text());
    }); //type 自动转为 xml
    });
    注意:如果载入的是 xml 文件,type 会智能判断。如果强行设置 html 类型返回,则会
    把 xml 文件当成普通数据全部返回,而不会按照 xml 格式解析数据。
    //使用$.get()异步返回 json
    $.get('test.json', function (response, status, xhr) {
    alert(response[0].url);
    });
    $.post()方法的使用和$.get()基本上一致,他们之间的区别也比较隐晦,基本都是背后的
    不同,在用户使用上体现不出。具体区别如下:
    1.GET 请求是通过 URL 提交的,而 POST 请求则是 HTTP 消息实体提交的;
    2.GET 提交有大小限制(2KB),而 POST 方式不受限制;
    3.GET 方式会被缓存下来,可能有安全性问题,而 POST 没有这个问题;
    4.GET 方式通过$_GET[]获取,POST 方式通过$_POST[]获取。
    //使用$.post()异步返回 html
    $.post('test.php', {
    url : 'ycku'
    }, function (response, status, xhr) {
    $('#box').html(response);
    });
    四.$.getScript() 和$.getJSON()
    jQuery 提供了一组用于特定异步加载的方法:$.getScript(),用于加载特定的 JS 文件;
    $.getJSON(),用于专门加载 JSON 文件。
    有时我们希望能够特定的情况再加载 JS 文件,而不是一开始把所有 JS 文件都加载了,
    这时课时使用$.getScript()方法。
    //点击按钮后再加载 JS 文件
    $('input').click(function () {
    $.getScript('test.js');
    });
    $.getJSON()方法是专门用于加载 JSON 文件的,使用方法和之前的类似。
    $('input').click(function () {
    $.getJSON('test.json', function (response, status, xhr) {
    alert(response[0].url);
    });
    });
    五.$.ajax()
    $.ajax()是所有 ajax 方法中最底层的方法,所有其他方法都是基于$.ajax()方法的封装。
    这个方法只有一个参数,传递一个各个功能键值对的对象。

    //$.ajax 使用
    $('input').click(function () {
    $.ajax({
    type : 'POST', //这里可以换成 GET
    url : 'test.php',
    data : {
    url : 'ycku'
    },
    success : function (response, stutas, xhr) {
    $('#box').html(response);
    }
    });
    });
    注意:对于 data 属性,如果是 GET 模式,可以使用三种之前说所的三种形式。如果是
    POST 模式可以使用之前的两种形式。
    六. 表单序列化
    Ajax 用的最多的地方莫过于表单操作,而传统的表单操作是通过 submit 提交将数据传
    输到服务器端。如果使用 Ajax 异步处理的话,我们需要将每个表单元素逐个获取才方能提
    交。这样工作效率就大大降低。
    //常规形式的表单提交
    $('form input[type=button]').click(function () {
    $.ajax({
    type : 'POST',
    url : 'test.php',
    data : {
    user : $('form input[name=user]').val(),
    email : $('form input[name=email]').val()
    },
    success : function (response, status, xhr) {
    alert(response);
    }
    });
    });
    使用表单序列化方法.serialize(),会智能的获取指定表单内的所有元素。这样,在面对
    大量表单元素时,会把表单元素内容序列化为字符串,然后再使用 Ajax 请求。
    //使用.serialize()序列化表单内容
    $('form input[type=button]').click(function () {
    $.ajax({
    type : 'POST',
    url : 'test.php',
    data : $('form').serialize(),
    success : function (response, status, xhr) {
    alert(response);
    }
    });
    });
    .serialize()方法不但可以序列化表单内的元素,还可以直接获取单选框、复选框和下拉
    列表框等内容。
    //使用序列化得到选中的元素内容
    $(':radio').click(function () {
    $('#box').html(decodeURIComponent($(this).serialize()));
    });
    除了.serialize()方法,还有一个可以返回 JSON 数据的方法:.serializeArray()。这个方法
    可以直接把数据整合成键值对的 JSON 对象。
    $(':radio').click(function () {
    console.log($(this).serializeArray());
    var json = $(this).serializeArray();
    $('#box').html(json[0].value);
    });
    有时,我们可能会在同一个程序中多次调用$.ajax()方法。而它们很多参数都相同,这
    个时候我们课时使用 jQuery 提供的$.ajaxSetup()请求默认值来初始化参数。
    $('form input[type=button]').click(function () {
    $.ajaxSetup({
    type : 'POST',
    url : 'test.php',
    data : $('form').serialize()
    });
    $.ajax({
    success : function (response, status, xhr) {
    alert(response);
    }
    });
    });
    在使用 data 属性传递的时候,如果是以对象形式传递键值对,可以使用$.param()方法
    将对象转换为字符串键值对格式。
    var obj = {a : 1, b : 2, c : 3};
    var form = $.param(obj);
    alert(form);
    注意:使用$.param()将对象形式的键值对转为 URL 地址的字符串键值对,可以更加稳
    定准确的传递表单内容。因为有时程序对于复杂的序列化解析能力有限,所以直接传递 obj
    对象要谨慎。
    一. 加载请求
    在 Ajax 异步发送请求时,遇到网速较慢的情况,就会出现请求时间较长的问题。而超
    过一定时间的请求,用户就会变得不再耐烦而关闭页面。而如果在请求期间能给用户一些提
    示,比如:正在努力加载中...,那么相同的请求时间会让用户体验更加的好一些。
    jQuery 提供了两个全局事件,.ajaxStart()和.ajaxStop()。这两个全局事件,只要用户触发
    了 Ajax,请求开始时(未完成其他请求)激活.ajaxStart(),请求结束时(所有请求都结束了)
    激活.ajaxStop()。
    //请求加载提示的显示和隐藏
    $('.loading').ajaxStart(function () {
    $(this).show();
    }).ajaxStop(function () {
    $(this).hide();
    });
    注意:以上代码在 jQuery1.8 及以后的版本不在有效,需要使用 jquery-migrate 向下兼容
    才能运行。新版本中,必须绑定在 document 元素上。
    $(document).ajaxStart(function () {
    $('.loading').show();
    }).ajaxStop(function () {
    $('.loading').hide();
    });
    //如果请求时间太长,可以设置超时
    $.ajax({
    timeout : 500
    });
    //如果某个 ajax 不想触发全局事件,可以设置取消
    $.ajax({
    global : false
    });
    二. 错误处理
    Ajax 异步提交时,不可能所有情况都是成功完成的,也有因为代码异步文件错误、网
    络错误导致提交失败的。这时,我们应该把错误报告出来,提醒用户重新提交或提示开发者
    进行修补。
    在之前高层封装中是没有回调错误处理的,比如$.get()、$.post()和.load()。所以,早期
    的方法通过全局.ajaxError()事件方法来返回错误信息。而在 jQuery1.5 之后,可以通过连缀
    处理使用局部.error()方法即可。而对于$.ajax()方法,不但可以用这两种方法,还有自己的属
    性方法 error : function () {}。
    //$.ajax()使用属性提示错误
    $.ajax({
    type : 'POST',
    url : 'test1.php',
    data : $('form').serialize(),
    success : function (response, status, xhr) {
    $('#box').html(response);
    },
    error : function (xhr, errorText, errorStatus) {
    alert(xhr.status + ':' + xhr.statusText);
    }
    });
    //$.post()使用连缀.error()方法提示错误,连缀方法将被.fail()取代
    $.post('test1.php').error(function (xhr, status, info) {
    alert(xhr.status + ':' +xhr.statusText);
    alert(status + ':' + info);
    });
    //$.post()使用全局.ajaxError()事件提示错误
    $(document).ajaxError(function (event, xhr, settings, infoError) {
    alert(xhr.status + ':' +xhr.statusText);
    alert(settings+ ':' + info);
    });
    三.请求全局事件
    jQuery 对于 Ajax 操作提供了很多全局事件方法,.ajaxStart()、.ajaxStop()、.ajaxError()
    等事件方法。他们都属于请求时触发的全局事件,除了这些,还有一些其他全局事件:
    .ajaxSuccess(),对应一个局部方法:.success(),请求成功完成时执行。
    .ajaxComplete(),对应一个局部方法:.complete(),请求完成后注册一个回调函数。
    .ajaxSend(),没有对应的局部方法,只有属性 beforeSend,请求发送之前要绑定的函数。
    //$.post()使用局部方法.success()
    $.post('test.php', $('form').serialize(), function (response, status, xhr) {
    $('#box').html(response);
    }).success(function (response, status, xhr) {
    alert(response);
    });
    //$.post()使用全局事件方法.ajaxSuccess()
    $(document).ajaxSuccess(function (event, xhr, settings) {
    alert(xhr.responseText);
    });
    注意:全局事件方法是所有 Ajax 请求都会触发到,并且只能绑定在 document 上。而局
    部方法,则针对某个 Ajax。
    对于一些全局事件方法的参数,大部分为对象,而这些对象有哪些属性或方法能调用,
    可以通过遍历方法得到。
    //遍历 settings 对象的属性
    $(document).ajaxSuccess(function (event, xhr, settings) {
    for (var i in settings) {
    alert(i);
    }
    });
    //$.post()请求完成的局部方法.complete()
    $.post('test.php', $('form').serialize(), function (response, status, xhr) {
    alert('成功');
    }).complete(function (xhr,status) {
    alert('完成');
    });
    //$.post()请求完成的全局方法.ajaxComplete()
    $(document).ajaxComplete(function (event, xhr, settings) {
    alert('完成');
    });
    //$.post()请求发送之前的全局方法.ajaxSend()
    $(document).ajaxSend(function (event, xhr, settings) {
    alert('发送请求之前');
    });
    //$.ajax()方法,可以直接通过属性设置即可。
    $.ajax({
    type : 'POST',
    url : 'test.php',
    data : $('form').serialize(),
    success : function (response, status, xhr) {
    $('#box').html(response);
    },
    complete : function (xhr, status) {
    alert('完成' + ' - ' + xhr.responseText + ' - ' + status);
    },
    beforeSend : function (xhr, settings) {
    alert('请求之前' + ' - ' + xhr.readyState + ' - ' + settings.url);
    }
    });
    注意:在 jQuery1.5 版本以后,使用.success()、.error()和.complete()连缀的方法,可以
    用.done()、.fail()和.always()取代。
    四.JSON  和 JSONP
    如果在同一个域下,$.ajax()方法只要设置 dataType 属性即可加载 JSON 文件。而在非
    同域下,可以使用 JSONP,但也是有条件的。
    //$.ajax()加载 JSON 文件
    $.ajax({
    type : 'POST',
    url : 'test.json',
    dataType : 'json',
    success : function (response, status, xhr) {
    alert(response[0].url);
    }
    });
    如果想跨域操作文件的话,我们就必须使用 JSONP。JSONP(JSON with Padding)是一个
    非官方的协议,它允许在服务器端集成 Script tags 返回至客户端,通过 javascript callback 的
    形式实现跨域访问(这仅仅是 JSONP 简单的实现形式)。
    //跨域的 PHP 端文件
    <?php
    $arr = array('a'=>1,'b'=>2,'c'=>3,'d'=>4,'e'=>5);
    $result = json_encode($arr);
    $callback = $_GET['callback'];
    echo $callback."($result)";
    ?>
    //$.getJSON()方法跨域获取 JSON
    $.getJSON('http://www.li.cc/test.php?callback=?', function (response) {
    console.log(response);
    });
    //$.ajax()方法跨域获取 JSON
    $.ajax({
    url : 'http://www.li.cc/test.php?callback=?',
    dataType : 'jsonp',
    success : function (response, status, xhr) {
    console.log(response);
    alert(response.a);
    }
    });
    五.jqXHR  对象
    在之前,我们使用了局部方法:.success()、.complete()和.error()。这三个局部方法并不
    是 XMLHttpRequest 对象调用的,而是$.ajax()之类的全局方法返回的对象调用的。这个对象,
    就是 jqXHR 对象,它是原生对象 XHR 的一个超集。
    //获取 jqXHR 对象,查看属性和方法
    var jqXHR = $.ajax({
    type : 'POST',
    url : 'test.php',
    data : $('form').serialize()
    });
    for (var i in jqXHR) {
    document.write(i + '<br />');
    }
    注意:如果使用 jqXHR 对象的话,那么建议用.done()、.always()和.fail()代
    替.success()、.complete()和.error()。以为在未来版本中,很可能将这三种方法废弃取消。
    //成功后回调函数
    jqXHR.done(function (response) {
    $('#box').html(response);
    });
    使用 jqXHR 的连缀方式比$.ajax()的属性方式有三大好处:
    1.可连缀操作,可读性大大提高;
    2.可以多次执行同一个回调函数;
    3.为多个操作指定回调函数;
    //同时执行多个成功后的回调函数
    jqXHR.done().done();
    //多个操作指定回调函数
    var jqXHR = $.ajax('test.php');
    var jqXHR2 = $.ajax('test2.php');
    $.when(jqXHR, jqXHR2).done(function (r1,r2) {
    alert(r1[0]);
    alert(r2[0]);
    });
  • 相关阅读:
    MVC三层架构
    JavaScript,你好!(二)
    HTML你好!
    Typora,你好!
    安装mysqlmysql-5.7.24-linux-glibc2.12-x86_64
    sizeof与strlen的区别
    printf格式化输出
    java泛型讲解
    双系统删除Linux系统
    kali破解wifi密码
  • 原文地址:https://www.cnblogs.com/zhang997050423/p/6829011.html
Copyright © 2011-2022 走看看