phyton 网站开发,哈尔滨建设银行网站首页,中国东盟建设集团有限公司网站,企业网站 多网站推广jQueryjQuery是JavaScript世界中使用最广泛的一个库。jQuery这么流行#xff0c;肯定是因为它解决了一些很重要的问题。实际上#xff0c;jQuery能帮我们干这些事情#xff1a;消除浏览器差异#xff1a;你不需要自己写冗长的代码来针对不同的浏览器来绑定事件#xff0c;…jQueryjQuery是JavaScript世界中使用最广泛的一个库。jQuery这么流行肯定是因为它解决了一些很重要的问题。实际上jQuery能帮我们干这些事情消除浏览器差异你不需要自己写冗长的代码来针对不同的浏览器来绑定事件编写AJAX等代码简洁的操作DOM的方法写$(#test)肯定比document.getElementById(test)来得简洁轻松实现动画、修改CSS等各种操作。jQuery的理念“Write Less, Do More“写更少的代码完成更多的工作jQuery有很多版本。但2.x移除了对古老的IE 6、7、8的支持因此2.x的代码更精简。选择哪个版本主要取决于你是否想支持IE 6~8。可以从jQuery官网可以下载最新版本。jQuery只是一个jquery-xxx.js文件但你会看到有compressed(已压缩)和uncompressed(未压缩)两种版本使用时完全一样但如果你想深入研究jQuery源码那就用uncompressed版本。使用jQuery使用jQuery只需要在页面的引入jQuery文件即可......如果网站本身已经引用了jQuery所以你可以直接使用use strict;console/log(jQuery版本 $.fn.jquery); //查看当前jQuery版本$符号$是著名的jQuery符号。实际上jQuery把所有功能全部封装在一个全局变量jQuery中而$也是一个合法的变量名它是变量jQuery的别名$window.jQuery; // jQuery(selector, context)window.$; // jQuery(selector, context)$ jQuery; // truetypeof($); // function$本质上就是一个函数但是函数也是对象于是$除了可以直接调用外也可以有很多其他属性。注意你看到的$函数名可能不是jQuery(selector, context)因为很多JavaScript压缩工具可以对函数名和参数改名所以压缩过的jQuery源码$函数可能变成a(b, c)。绝大多数时候我们都直接用$(因为写起来更简单嘛)。但是如果$这个变量不幸地被占用了而且还不能改那我们就只能让jQuery把$变量交出来然后就只能使用jQuery这个变量$; //jQuery(selector, context)jQuery.noConflict();$; // undefinedjQuery; // jQuery(selector, context)这种黑魔法的原理是jQuery在占用$之前先在内部保存了原来的$,调用jQuery.noConflict()时会把原来保存的变量还原。选择器选择器是jQuery的核心。一个选择器写出来类似$(#dom-id)。为什么jQuery要发明选择器回顾一下DOM操作中我们经常使用的代码// 按ID查找var a document.getElementById(dom-id);这些代码实在太繁琐了很多时候需要递归查找所有子节点。jQuery的选择器就是帮助我们快速定位到一个或多个DOM节点。按ID查找如果某个DOM节点有id属性利用jQuery查找如下// 查找:var div $(#abc);注意#abc以#开头。返回的对象是jQuery对象。什么是jQuery对象jQuery对象类似数组它的每个元素都是一个引用了DOM节点的对象。以上面的查找为例如果id为abc的存在返回的jQuery对象如下[...]如果id为abc的不存在返回的jQuery对象如下[]总之jQuery的选择器不会返回undefined或者null这样的好处是你不必在下一行判断if (div undefined)。jQuery对象和DOM对象之间可以互相转化var div $(#abc); //jQuery对象var divDom div.get(0); //假设存在div获取第一个DOM元素var another $(divDom); //重新把DOM包装成jQuery对象通常情况下你不需要获取DOM对象直接使用jQuery对象更加方便。如果你拿到了一个DOM对象那可以简单地调用$(aDomObject)把它变成jQuery对象这样就可以方便地使用jQuery的API了。按tag查找按tag查找只需要写上tag名称就可以了var ps $(p); // 返回所有节点ps.length; // 数一数页面有多少个节点按class查找按class查找注意在class名称前加一个.var a $(.red); // 所有节点包含classred都将返回// 例如:// ...// ...通常很多节点有多个class我们可以查找同时包含red和green的节点var a $(.red.green); // 注意没有空格// 符合条件的节点// ...// ...按属性查找一个DOM节点除了id和class外还可以有很多属性很多时候按属性查找会非常方便比如在一个表单中按属性来查找var email $([nameemail]); // 找出?? nameemailvar passwordInput $([typepassword]); // 找出?? typepasswordvar a $([itemsA B]); // 找出?? itemsA B当属性的值包含空格等特殊字符时需要用双引号括起来。按属性查找还可以使用前缀查找或者后缀查找var icons $([name^icon]); // 找出所有name属性值以icon开头的DOM// 例如: nameicon-1, nameicon-2var names $([name$with]); // 找出所有name属性值以with结尾的DOM// 例如: namestartswith, nameendswith这个方法尤其适合通过class属性查找且不受class包含多个名称的影响var icons $([class^icon-]); // 找出所有class包含至少一个以icon-开头的DOM// 例如: classicon-clock, classabc icon-home组合查找组合查找就是把上述简单选择器组合起来使用。如果我们查找$([nameemail])很可能把表单外的也找出来但我们只希望查找就可以这么写var emailInput $(input[nameemail]); // 不会找出同样的根据tag和class来组合查找也很常见var tr $(tr.red); // 找出...多项选择器多项选择器就是把多个选择器用,组合起来一块选$(p,div); // 把和都选出来$(p.red,p.green); // 把和都选出来要注意的是选出来的元素是按照它们在HTML中出现的顺序排列的而且不会有重复元素。例如不会被上面的$(p.red,p.green)选择两次。层级选择器除了基本的选择器外jQuery的层级选择器更加灵活也更强大。因为DOM的结构就是层级结构所以我们经常要根据层级关系进行选择。层级选择器(Descendant Selector)如果两个DOM元素具有层级关系就可以用$(ancestor descendant)来选择层级之间用空格隔开。例如JavaScriptPythonLua要选出JavaScript可以用层级选择器$(ul.lang li.lang-javascript); // [JavaScript]$(div.testing li.lang-javascript);//[JavaScript]这种层级选择器相比单个的选择器好处在于它缩小了选择范围因为首先要定位父节点才能选择相应的子节点这样避免了页面其他不相关的元素。例如$(form[nameupload] input);就把选择范围限定在name属性为upload的表单里。如果页面有很多表单其他表单的不会被选择。多层选择也是允许的$(form.test p input); // 在form表单选择被包含的子选择器(Child Selector)子选择器$(parentchild)类似层级选择器但是限定了层级关系必须是父子关系就是节点必须是节点的直属子节点。还是以上面的例子$(ul.langli.lang-javascript);//可以选出[JavaScript]$(div.testingli.lang-javascript); // [], 无法选出因为和不构成父子关系过滤器(Filter)过滤器一般不单独使用它通常附加在选择器上帮助我们更精确地定位元素。观察过滤器的效果$(ul.lang li); //选出JavaScript、Python和Lua 3个节点$(ul.lang li:first-child); // 仅选出JavaScript$(ul.lang li:last-child); // 仅选出Lua$(ul.lang li:nth-child(2)); // 选出第N个元素N从1开始$(ul.lang li:nth-child(even)); // 选出序号为偶数的元素$(ul.lang li:nth-child(odd)); // 选出序号为奇数的元素表单相关针对表单元素jQuery还有一组特殊的选择器:input可以选择和:file可以选择和input[typefile]一样:checkbox可以选择复选框和input[typecheckbox]一样:radio可以选择单选框和input[typeradio]一样:focus可以选择当前输入焦点的元素例如把光标放到一个上用$(input:focus)就可以选出:checked选择当前勾上的单选框和复选框用这个选择器可以立刻获得用户选择的项目如$(input[typeradio]:checked):enabled可以选择可以正常输入的、 等也就是没有灰掉的输入:disabled和:enabled正好相反选择那些不能输入的。此外jQuery还有很多有用的选择器例如选出可见的或隐藏的元素$(div:visible); // 所有可见的div$(div:hidden); // 所有隐藏的div查找和过滤通常情况下选择器可以直接定位到我们想要的元素但是当我们拿到一个jQuery对象后还可以以这个对象为基准进行查找和过滤。最常见的查找是在某个节点的所有子节点中查找使用find()方法它本身又接收一个任意的选择器。例如如下的HTML结构JavaScriptPythonSwiftSchemeHaskell用find()查找var ul $(ul.lang); // 获得var dy ul.find(.dy); // 获得JavaScript, Python, Schemevar swf ul.find(#swift); // 获得Swiftvar hsk ul.find([namehaskell]); // 获得Haskell如果要从当前节点开始向上查找使用parent()方法var swf $(#swift); //获得Swiftvar parent swf.parent(); //获得Swift的上层节点var a swf.parent(.red);//获得Swift的上层节点同时传入过滤条件。如果ul不符合条件返回空jQuery对象对于位于同一层级的节点可以通过next()和prev()方法例如当我们已经拿到Swift节点后var swift $(#swift);swift.next(); //Schemeswift.next([namehaskell]);// 空的jQuery对象因为Swift的下一个元素Scheme不符合条件[namehaskell]swift.prev(); //Pythonswift.prev(.dy); //Python因为Python同时符合过滤器条件.dy过滤和函数式编程的map、filter类似jQuery对象也有类似的方法。filter()方法可以过滤掉不符合选择器条件的节点var langs $(ul.lang li); // 拿到JavaScript, Python, Swift, Scheme和Haskellvar a langs.filter(.dy); // 拿到JavaScript, Python, Scheme或者传入一个函数要特别注意函数内部的this被绑定为DOM对象不是jQuery对象var langs $(ul.lang li);// 拿到JavaScript, Python, Swift, Scheme和Haskelllangs.filter(function () {return this.innHTML.indexOf(S) 0;//返回S开头的节点}); //拿到SwiftSchememap()方法把一个jQuery对象包含的若干DOM节点转化为其他对象var langs $(ul.lang li); // 拿到JavaScript, Python, Swift, Scheme和Haskellvar arr langs.map(function () {return this.innerHtml;}).get(); // 用get()拿到包含string的Array[JavaScript, Python, Swift, Scheme, Haskell]此外一个jQuery对象如果包含了不止一个DOM节点first()、last()和slice()方法可以返回一个新的jQuery对象把不需要的DOM节点去掉var langs $(ul.lang li); // 拿到JavaScript, Python, Swift, Scheme和Haskellvar js langs.first();练习对于下面的表单Name: Email: Password: Gender: Male FemaleCity: BeijingShanghaiChengduXiamenSubmit输入值后用jQuery获取表单的JSON字符串key和value分别对应每个输入的name和相应的value例如{name:Michael,email:...}use strict;var json null;//答案1var input $(#test-form [name]);var json {};for (var i 0; i input.length; i) {if (input[i].name gender) {if (!input[i].checked) continue;};json[input[i].name] input[i].value;};json JSON.stringify(json);//答案2var input $(#test-form [name]);for (var i 0; i input.length; i) {if (input[i].name gender) {if (!input[i].checked) continue;}json ( input[i].name : input[i].value );if (i ! input.length - 1) json ,}json };操作DOMjQuery的选择器很强大用起来又简单又灵活但是搞了这么久拿到了jQuery对象下一步当然是操作对应的DOM节点啦回顾一下修改DOM的CSS、文本、设置HTML有多么麻烦而且有的浏览器只有innerHTML有的浏览器支持innerText有了jQuery对象不需要考虑浏览器差异了全部统一操作修改Text和HTMLjQuery对象的text()和html()方法分别获取节点的文本和原始HTML文本例如如下的HTML结构JavaScriptJava JavaScript分别获取文本和HTML$(#test-ul li[namebook]).text(); // Java JavaScript$(#test-ul li[namebook]).html(); // Java JavaScript如何设置文本或HTMLjQuery的API设计非常巧妙无参数调用text()是获取文本传入参数就变成设置文本HTML也是类似操作use strict;var j1 $(#test-ul li.js);var j2 $(#test-ul li[namebook]);一个jQuery对象可以包含0个或任意个DOM对象它的方法实际上会作用在对应的每个DOM节点上。在上面的例子中试试$(#test-ul li).text(JS); // 是不是两个节点都变成了JS所以jQuery对象的另一个好处是我们可以执行一个操作作用在对应的一组DOM节点上。即使选择器没有返回任何DOM节点调用jQuery对象的方法仍然不会报错// 如果不存在id为not-exist的节点$(#not-exist).text(Hello); // 代码不报错没有节点被设置为Hello这意味着jQuery帮你免去了许多if语句。修改CSSjQuery对象有“批量操作”的特点这用于修改CSS实在是太方便了。考虑下面的HTML结构JavaScriptJavaPythonSwiftScheme要高亮显示动态语言调用jQuery对象的css(name, value)方法我们用一行语句实现use strict;$(#test-css li.dyspan).css(background-color, #ffd351);注意jQuery对象的所有方法都返回一个jQuery对象(可能是新的也可能是自身)这样我们可以进行链式调用非常方便。jQuery对象的css()方法可以这么用var div $(#test-div);div.css(color); //#000033, 获取CSS属性div.css(color, #336699); // 设置CSS属性div.css(color, ); // 清除CSS属性为了和JavaScript保持一致CSS属性可以用background-color和backgroundColor两种格式。css()方法将作用于DOM节点的style属性具有最高优先级。如果要修改class属性可以用jQuery提供的下列方法var div $(#test-div);div.hasClass(highlight); // false class是否包含highlightdiv.addClass(highlight); // 添加highlight这个classdiv.removeClass(highlight); // 删除highlight这个class练习分别用css()方法和addClass()方法高亮显示JavaScript.highlight {color: #dd1144;background-color: #ffd351;}PythonJavaScriptSwiftHaskelluse strict;//TODOvar div $(#test-highlight-css);var js div.find(.js);js.css(color,#dd1144).css(background-color,#ffd351);显示和隐藏DOM要隐藏一个DOM我们可以设置CSS的display属性为none利用css()方法就可以实现。不过要显示这个DOM就需要恢复原有的display属性这就得先记下来原有的display属性到底是block还是inline还是别的值。考虑到显示和隐藏DOM元素使用非常普遍jQuery直接提供show()和hide()方法我们不用关心它是如何修改display属性的总之它能正常工作var a $(a[target_blank]);a.hide(); //隐藏a.show(); //显示注意隐藏DOM节点并未改变DOM树的结构它只影响DOM节点的显示。这和删除DOM节点是不同的。获取DOM信息//浏览器可视窗口大小:$(window).width(); //800$(window).height(); //600//HTML文档大小$(document).width(); //800$(document).height(); //3500//某个div的大小var div $(#test-div);div.width(); //600div.heigth(); //300div.width(400); // 设置CSS属性 width: 400px是否生效要看CSS是否有效div.height(200px); // 设置CSS属性 height: 200px是否生效要看CSS是否有效attr()和removeAttr()方法用于操作DOM节点的属性// ...var div $(#test-div);div.attr(data); // undefined, 属性不存在div.attr(name); // Testdiv.attr(name, Hello); // div的name属性变为Hellodiv.removeAttr(name); // 删除name属性div.attr(name); // undefinedprop()方法和attr()类似但是HTML5规定有一种属性在DOM节点中可以没有值只有出现与不出现两种例如等价于attr()和prop()对于属性checked处理有所不同var radio $(#test-radio);radio.attr(checked); // checkedradio.prop(checked); // trueprop()返回值更合理一些。不过用is()方法判断更好var radio $(#test-radio);radio.is(:checked); // true类似的属性还有selected处理时最好用is(:selected)。操作表单对于表单元素jQuery对象统一提供val()方法获取和设置对应的value属性/*BeijingShanghaiShenzhenHello*/varinput $(#test-input),select $(#test-select),textarea $(#test-textarea);input.val(); // testinput.val(abcexample.com); // 文本框的内容已变为abcexample.comselect.val(); // BJselect.val(SH); // 选择框已变为Shanghaitextarea.val(); // Hellotextarea.val(Hi); // 文本区域已更新为Hi可见一个val()就统一了各种输入框的取值和赋值的问题。修改DOM结构直接使用浏览器提供的API对DOM结构进行修改不但代码复杂而且要针对浏览器写不同的代码。有了jQuery我们就专注于操作jQuery对象本身底层的DOM操作由jQuery完成就可以了这样一来修改DOM也大大简化了。添加DOM要添加新的DOM节点除了通过jQuery的html()这种暴力方法外还可以用append()方法例如JavaScriptPythonSwift如何向列表新增一个语言首先要拿到节点var ul $(#test-divul);然后调用append()传入HTML片段ul.append(Haskell);除了接受字符串append()还可以传入原始的DOM对象jQuery对象和函数对象// 创建DOM对象:var ps document.createElement(li);ps.innerHTML Pascal;// 添加DOM对象:ul.append(ps);// 添加jQuery对象:ul.append($(#scheme));// 添加函数对象:ul.append(function (index, html) {return Language - index ;});传入函数时要求返回一个字符串、DOM对象或者jQuery对象。因为jQuery的append()可能作用于一组DOM节点只有传入函数才能针对每个DOM生成不同的子节点。append()把DOM添加到最后prepend()则把DOM添加到最前。另外注意如果要添加的DOM节点已经存在于HTML文档中它会首先从文档移除然后再添加也就是说用append()你可以移动一个DOM节点。如果要把新节点插入到指定位置例如JavaScript和Python之间那么可以先定位到JavaScript然后用after()方法var js $(#test-divulli:first-child);js.after(Lua);也就是说同级节点可以用after()或者before()方法。删除节点要删除DOM节点拿到jQuery对象后直接调用remove()方法就可以了。如果jQuery对象包含若干DOM节点实际上可以一次删除多个DOM节点var li $(#test-divulli);li.remove(); // 所有全被删除练习修改DOM结构阅读: 31717直接使用浏览器提供的API对DOM结构进行修改不但代码复杂而且要针对浏览器写不同的代码。有了jQuery我们就专注于操作jQuery对象本身底层的DOM操作由jQuery完成就可以了这样一来修改DOM也大大简化了。添加DOM要添加新的DOM节点除了通过jQuery的html()这种暴力方法外还可以用append()方法例如JavaScriptPythonSwift如何向列表新增一个语言首先要拿到节点var ul $(#test-divul);然后调用append()传入HTML片段ul.append(Haskell);除了接受字符串append()还可以传入原始的DOM对象jQuery对象和函数对象// 创建DOM对象:var ps document.createElement(li);ps.innerHTML Pascal;// 添加DOM对象:ul.append(ps);// 添加jQuery对象:ul.append($(#scheme));// 添加函数对象:ul.append(function (index, html) {return Language - index ;});传入函数时要求返回一个字符串、DOM对象或者jQuery对象。因为jQuery的append()可能作用于一组DOM节点只有传入函数才能针对每个DOM生成不同的子节点。append()把DOM添加到最后prepend()则把DOM添加到最前。另外注意如果要添加的DOM节点已经存在于HTML文档中它会首先从文档移除然后再添加也就是说用append()你可以移动一个DOM节点。如果要把新节点插入到指定位置例如JavaScript和Python之间那么可以先定位到JavaScript然后用after()方法var js $(#test-divulli:first-child);js.after(Lua);也就是说同级节点可以用after()或者before()方法。删除节点要删除DOM节点拿到jQuery对象后直接调用remove()方法就可以了。如果jQuery对象包含若干DOM节点实际上可以一次删除多个DOM节点var li $(#test-divulli);li.remove(); // 所有全被删除练习除了列出的3种语言外请再添加Pascal、Lua和Ruby然后按字母顺序排序节点JavaScriptPythonSwift//答案1var ul $(#test-divul);var lan [Pascal, Lua, Ruby];//获取原来的内容var n ul.find(span).map(function () {return $(this).text(); //$(this)转成jQuery对象}).get();//把原来的内容和新内容结合起来然后排序lan lan.concat(n).sort();//加入html标签转化成字符串var strlan lan.map(function (a) {return a ;}).join();//更改ul的结构ul.html(strlan);//答案2var ul $(#test-divul);var arr [Pascal, Lua, Ruby];ul.find(span).map(function (item) {arr.push($(this).text());});arr.sort();ul.find(li).remove(); //一开始写成ul.remove()结果无法append没有任何显示因为remove把也删了导致添加了无法显示arr.map(function (e) {ul.append( e );});事件因为JavaScript在浏览器中以单线程模式运行页面加载后一旦页面上所有的JavaScript代码被执行完后就只能依赖触发事件来执行JavaScript代码。浏览器在接收到用户的鼠标或键盘输入后会自动在对应的DOM节点上触发相应的事件。如果该节点已经绑定了对应的JavaScript处理函数该函数就会自动调用。由于不同的浏览器绑定事件的代码都不太一样所以用jQuery来写代码就屏蔽了不同浏览器的差异我们总是编写相同的代码。举个例子假设要在用户点击了超链接时弹出提示框我们用jQuery这样绑定一个click事件/* HTML:** 点我试试**///获取超链接的jQuery对象var a $(#test-link);a.on(click, function () {alert(Hello!);});on方法用来绑定一个事件我们需要传入事件名称和对应的处理函数。另一种更简化的写法是直接调用click()方法a.click(function () {alert(Hello!);});两者完全等价。我们通常用后面的写法。jQuery能够绑定的事件主要包括鼠标事件click鼠标单击时触发dbclick鼠标双击时触发mouseenter鼠标进入时触发mouseleave鼠标移出时触发mousemove鼠标在DOM内部移动时触发hover鼠标进入和退出时触发两个函数相当于mouseenter加上mouseleave。键盘事件键盘事件仅作用在当前焦点的DOM上通常是和。keydown键盘按下时触发keyup键盘松开时触发keypress按一次键后触发其他事件focus当DOM获得焦点时触发blur当DOM获得焦点时触发change当、或的内容改变时触发submit当提交时触发ready当页面被载入并且DOM树完成初始化后触发其中ready仅作用于document对象。由于ready事件在DOM完成初始化后触发且只触发一次所以非常适合用来写其他的初始化代码。假设我们想给一个表单绑定submit事件下面的代码没有预期的效果// 代码有误:$(#testForm).on(submit, function () {alert(submit!);});...因为JavaScript在此执行的时候尚未载入浏览器所以$(#testForm)返回[]并没有绑定事件到任何DOM上。所以我们自己的初始化代码必须放到document对象的ready事件中保证DOM已完成初始化$(document).on(ready, function () {$(#testForm).on(submit, function () {alert(submit!);});});...这样写就没有问题了。因为相关代码会在DOM树初始化后再执行。由于ready事件使用非常普遍所以可以这样简化$(document).ready(function () {//on(submit, function)也可以这么简化$(#testForm).submit(function () {alert(submit!);});});甚至还可以简化$(function () {//init...});上面的这种写法最为常见。如果你遇到$(function () {...})的形式牢记这是document对象的ready事件处理函数。完全可以反复绑定事件处理函数它们会依次执行$(function () {console.log(init A...);});$(function () {console.log(init B...);});事件参数有些事件如mousemove和keypress我们需要获取鼠标位置和按键的值否则监听这些事件就没什么意义了。所有事件都会传入Event对象作为参数可以从Event对象上获取到更多的信息$(function () {$(#testMouseMoveDiv).mousemove(function (e) {$(#testMouseMoveSpan).text(pageX e.pageX , pageY e.pageY);});});取消绑定一个已被绑定的事件可以接触绑定通过off(click, function)实现function hello () {alert(hello!);}a.click(hello); //确定事件//10秒后接触绑定setTimeout(function () {a.off(click,hello);}, 10000);需要特别注意的是下面这种写法是无效的// 绑定事件:a.click(function () {alert(hello!);});// 解除绑定:a.off(click, function () {alert(hello!);});这是因为两个匿名函数虽然长得一模一样但是它们是两个不同的函数对象off(click, function () {...})无法移除已绑定的第一个匿名函数。为了实现移除效果可以使用off(click)一次性移除已绑定的click事件的所有处理函数。同理无参数调用off()一次性移除已绑定的所有类型的事件处理函数。事件触发条件一个需要注意的问题是事件的触发总是由用户操作引发的。例如我们监控文本框的内容改动var input $(#test-input);input.change(function () {console.log(changed...);});当用户在文本框中输入时就会触发change事件。但是如果用JavaScript代码去改动文本框的值将不会触发change事件var input $(#test-input);input.val(change it!); // 无法触发change事件有些时候我们希望用代码触发change事件可以直接调用无参数的change()方法来触发该事件var input $(#test-input);input.val(change it!);input.change(); // 触发change事件input.change()相当于input.trigger(change)它是trigger()方法的简写。为什么我们希望手动触发一个事件呢如果不这么做很多时候我们就得写两份一模一样的代码。浏览器安全限制在浏览器中有些JavaScript代码只有在用户触发下才能执行例如window.open()函数// 无法弹出新窗口将被浏览器屏蔽:$(function () {window.open(/);});这些“敏感代码”只能由用户操作来触发var button1 $(#testPopupButton1);var button2 $(#testPopupButton2);function popupTestWindow() {window.open(/);}button1.click(function () {popupTestWindow();});button2.click(function () {// 不立刻执行popupTestWindow()100毫秒后执行:setTimeout(popupTestWindow, 100);});当用户点击button1时click事件被触发由于popupTestWindow()在click事件处理函数内执行这是浏览器允许的而button2的click事件并未立刻执行popupTestWindow()延迟执行的popupTestWindow()将被浏览器拦截。练习对如下的Form表单请选择想要学习的编程语言全选全不选 反选 JavaScript Python Ruby Haskell SchemeSubmit绑定合适的事件处理函数实现以下逻辑当用户勾上“全选”时自动选中所有语言并把“全选”变成“全不选”当用户去掉“全不选”时自动不选中所有语言当用户点击“反选”时自动把所有语言状态反转(选中的变为未选未选的变为选中)当用户把所有语言都手动勾上时“全选”被自动勾上并变为“全不选”当用户手动去掉选中至少一种语言时“全不选”自动被去掉选中并变为“全选”。use strict; var form $(#test-form), langs form.find([namelang]), selectAll form.find(label.selectAll :checkbox), selectAllLabel form.find(label.selectAll span.selectAll), deselectAllLabel form.find(label.selectAll span.deselectAll), invertSelect form.find(a.invertSelect); // 重置初始化状态: form.find(*).show().off(); form.find(:checkbox).prop(checked, false).off(); deselectAllLabel.hide(); // 拦截form提交事件: form.off().submit(function (e) { e.preventDefault(); alert(form.serialize()); });//练习答案selectAll.change(function () {if (this.checked) {langs.prop(checked, true);deselectAllLabel.show();selectAllLabel.hide();} else {langs.prop(checked, false);deselectAllLabel.hide();selectAllLabel.show();}})invertSelect.click(function () {langs.each(function () {if (this.checked) {$(this).prop(checked, false);} else {this.checked true;}})})//alert(langs.length);var count 0,len langs.length;langs.click(function () {count 0;langs.each(function () {if (this.checked)count;})if (count len) {selectAll.prop(checked, true);deselectAllLabel.show();selectAllLabel.hide();} else {selectAllLabel.show();deselectAllLabel.hide();selectAll.prop(checked, false);}})动画用JavaScript实现动画原理非常简单我们只需要以固定的时间间隔(例如0.1秒)每次把DOM元素的CSS样式修改一点(例如高宽各增加10%)看起来就像动画了。但是要用JavaScript手动实现动画效果需要编写非常复杂的代码。如果想要把动画效果用函数封装起来便于复用那考虑的事情就更多了。使用jQuery实现动画代码已经简单得不能再简化了只需要一行代码让我们先来看看jQuery内置的几种动画样式show / hide直接以无参数形式调用show()和hide()会显示和隐藏DOM元素。但是只要传递一个时间参数进去就变成了动画var div $(#test-show-hide);div.hide(3000); // 在3秒钟内逐渐消失时间以毫秒为单位但也可以是slowfast这些字符串var div $(#test-show-hide);div.show(slow); // 在0.6秒钟内逐渐显示toggle()方法则根据当前状态决定是show()还是hide()。slideUp / slideDown你可能已经看出来了show()和hide()是从左上角逐渐展开或收缩的而slideUp()和slideDown()则是在垂直方向逐渐展开或收缩的。slideUp()把一个可见的DOM元素收起来效果跟拉上窗帘似的slideDown()相反而slideToggle()则根据元素是否可见来决定下一步动作var div $(#test-slide);div.slideUp(3000); // 在3秒钟内逐渐向上消失fadeIn / fadeOutfadeIn()和fadeOut()的动画效果是淡入淡出也就是通过不断设置DOM元素的opacity属性来实现而fadeToggle()则根据元素是否可见来决定下一步动作var div $(#test-fade);div.fadeOut(slow); // 在0.6秒内淡出自定义动画如果上述动画效果还不能满足你的要求那就祭出最后大招animate()它可以实现任意动画效果我们需要传入的参数就是DOM元素最终的CSS状态和时间jQuery在时间段内不断调整CSS直到达到我们设定的值var div $(#test-animate);div.animate({opacity: 0.25,width: 256px,height: 256px}, 3000); //在3秒内css过渡到设定值animate()还可以再传入一个函数当动画结束时该函数将被调用var div $(#test-animate);div.animate({opacity: 0.25,width: 256px,height: 256px}, 3000, function () {console.log(动画已结束);//回复初始状态$(this).css(opacity, 1.0).css(width, 128px).css(heght, 128px);});实际上这个回调函数参数对于基本动画也是适用的。有了animate()你就可以实现各种自定义动画效果了。串行动画jQuery的动画还可以串行动画通过delay()方法还可以实现暂停这样我们可以实现更复杂的动画效果而代码却相当简单var div $(#test-animates);//动画效果slideDown - 暂停 - 放大 - 暂停 - 缩小div.slideDown(2000).delay(1000).animate({width: 256px,heght: 256px}, 2000).delay(1000).animate({width: 128px,height: 128px}, 2000);因为动画需要执行一段时间所以jQuery必须不断返回新的Promise对象才能后续执行操作。简单地把动画封装在函数中是不够的。为什么有的动画没有效果你可能会遇到有的动画如slideUp()根本没有效果。这是因为jQuery动画的原理是逐渐改变CSS的值如height从100px逐渐变为0。但是很多不是block性质的DOM元素对它们设置height根本就不起作用所以动画也就没有效果。此外jQuery也没有实现对background-color的动画效果用animate()设置background-color也没有效果。这种情况下可以使用CSS3的transition实现动画效果。AJAX用JavaScript写AJAX前面已经介绍过了主要问题就是不同浏览器需要写不同代码并且状态和错误处理写起来很麻烦。用jQuery的相关对象来处理AJAX不但不需要考虑浏览器问题代码也能大大简化。ajax()jQuery在全局对象jQuery(也就是$)绑定了ajax()函数可以处理AJAX请求。ajax(url, settings)函数需要接收一个URL和一个可选的settings对象常用的选项如下async是否异步执行AJAX请求默认为true千万不要指定为falsemethod发送的Method缺省为GET可指定为POST、PUT等contentType发送POST请求的格式默认值为application/x-www-form-urlencoded; charsetUTF-8也可以指定为text/plain、application/jsondata发送的数据可以是字符串、数组或object。如果是GET请求data将被转换成query附加到URL上如果是POST请求根据contentType把data序列化成合适的格式headers发送的额外的HTTP头必须是一个objectdataType接收的数据格式可以指定为html、xml、json、text等缺省情况下根据响应的Content-Type猜测。下面的例子发送一个GET请求并返回一个JSON格式的数据var jqxhr $.ajax(/api/categories, {dataType: json});//请求已经发送出去了不过如何用回调函数处理返回的数据和出错时的响应呢还记得Promise对象吗jQuery的jqXHR对象类似一个Promise对象我们可以用链式写法来处理各种回调use strict;function ajaxLog(s) {var txt $(#test-response-text);txt.val(txt.val() \n s);}$(#test-response-text).val();//Todovar jqxhr $.ajax(/api/categories, {dataType: json}).done(function (data) {ajaxLog(成功, 收到的数据: JSON.stringify(data));}).fail(function (xhr, status) {ajaxLog(失败: xhr.status , 原因: status);}).always(function () {ajaxLog(请求完成: 无论成功或失败都会调用);});get对常用的AJAX操作jQuery提供了一些辅助方法。由于GET请求最常见所以jQuery提供了get()方法可以这么写var jqxhr $.get(/path/to/resource, {name: Bob Lee,check: 1});第二个参数如果是objectjQuery自动把它变成query string然后加到URL后面实际的URL是/path/to/resource?nameBob%20Leecheck1这样我们就不用关心如何用URL编码并构造一个query string了。postpost()和get()类似但是传入的第二个参数默认被序列化为application/x-www-form-urlencodedvar jqxhr $.post(/path/to/resource, {name: Bob Lee,check: 1});实际构造的数据nameBob%20Leecheck1作为POST的body被发送。getJSON由于JSON用得越来越普遍所以jQuery也提供了getJSON()方法来快速通过GET获取一个JSON对象var jqxhr $.getJSON(/path/to/resource, {name: Bob Lee,check: 1}).done(function (data) {// data已经被解析为JSON对象了});安全限制jQuery的AJAX完全封装的是JavaScript的AJAX操作所以它的安全限制和前面讲的用JavaScript写AJAX完全一样。如果需要使用JSONP可以在ajax()中设置jsonp: callback让jQuery实现JSONP跨域加载数据。关于跨域的设置请参考浏览器 - AJAX一节中CORS的设置。扩展当我们使用jQuery对象的方法时由于jQuery对象可以操作一组DOM而且支持链式操作所以用起来非常方便。但是jQuery内置的方法永远不可能满足所有的需求。比如我们想要高亮显示某些DOM元素用jQuery可以这么实现$(span.h1).css(backgroundColor, #fffceb).css(color, #d85030);$(p a.h1).css(backgroundColor, #fffceb).css(color, #d85030);总是写重复代码可不好万一以后还要修改字体就更麻烦了能不能统一起来写个highlight()方法$(span.hl).highlight();$(p a.hl).highlight();答案是肯定的。我们可以扩展jQuery来实现自定义方法。将来如果要修改高亮的逻辑只需修改一处扩展代码。这种方式也称为编写jQuery插件。编写jQuery插件给jQuery对象绑定一个新方法是通过扩展$.fn对象实现的。让我们来编写第一个扩展——highlight1()$.fn.highlight1 function () {//this以绑定为当前jQuery对象this.css(backgroundColor, #fffceb).css(color,#d85030);return this;}注意到函数内部的this在调用时被绑定为jQuery对象所以函数内部代码可以正常调用所有jQuery对象的方法。对于如下的HTML结构什么是jQueryjQuery是目前最流行的JavaScript库。来测试一下highlight1()的效果use strict;$(#test-highlight1 span).highlight1();可能发现了为什么最后要return this;因为jQuery对象支持链式操作我们自己写的扩展方法也要能继续链式下去$(span h1).highlight1().slideDown();不然用户调用的时候就不得不把上面的代码拆成两行。但是这个版本并不完美。有的用户希望高亮的颜色能自己来指定怎么办我们可以给方法加个参数让用户自己把参数用对象传进去。于是我们有了第二个版本的highlight2()$.fn.highlight2 function (option) {//要考虑到各种情况://options为undefined//options只有部分keyvar bgcolor options options.backgroundColor || #fffceb;var color options options.color || #d85030;this.css(backgroundColor, bgcolor).css(color, color);return this;}对于如下HTML结构什么是jQuery Plugin编写jQuery Plugin可以用来扩展jQuery的功能。来实测一下带参数的highlight2()use strict;$(#test-highlight2 span).highlight2({backgroundColor: #00a8e6,color: #ffffff});对于默认值的处理我们用了一个简单的和||短路操作符总能得到一个有效的值。另一种方法是使用jQuery提供的辅助方法$.extend(target, obj1, obj2, ...)它把多个object对象的属性合并到第一个target对象中遇到同名属性总是使用靠后的对象的值也就是越往后优先级越高//把默认值和用户传入的options合并到对象{}中并返回:var opts $.extend({}, {backgroundColor: #00a8e6,color: fffff}, options);紧接着用户对highlight2()提出了意见每次调用都需要传入自定义的设置能不能让我自己设定一个缺省值以后的调用统一使用无参数的highlight2()也就是说我们设定的默认值应该能允许用户修改。那默认值放哪比较合适放全局变量肯定不合适最佳地点是$.fn.highlight2这个函数对象本身。于是最终版的highlight()终于诞生了$.fn.highlight function (options) {//合并默认值和用户设定值var opts $.extend({}, $.fn.highlight.defaults, options);this.css(backgroundColor, opts.backgroundColor).css(color, opts.color);return this;}//设定默认值$.fn.highlight.defaults {color: #d85030,backgroundColor: #fff8de}这次用户终于满意了。用户使用时只需一次性设定默认值$.fn.highlight.defaults.color #fff;$.fn.highlight.defaults.backgroundColor #000;然后就可以非常简单地调用highlight()了。对如下的HTML结构如何编写jQuery Plugin编写jQuery Plugin要设置默认值并允许用户修改默认值或者运行时传入其他值。实测一下修改默认值的效果use strict;$.fn.highlight.defaults.color #659f13;$.fn.highlight.defalts.backgroundColor #f2fae3;$(#test-highlight p:first-child span).highlight();$(#test-highlight p:last-child span).highlight({color: #dd1144});最终我们得出编写一个jQuery插件的原则给$.fn绑定函数实现插件的代码逻辑插件函数最后要return this;以支持链式调用插件函数要有默认值绑定在$.fn..defaults上用户在调用时可传入设定值以便覆盖默认值。针对特定元素的扩展我们知道jQuery对象的有些方法只能作用在特定DOM元素上比如submit()方法只能针对form。如果我们编写的扩展只能针对某些类型的DOM元素应该怎么写还记得jQuery的选择器支持filter()方法来过滤吗我们可以借助这个方法来实现针对特定元素的扩展。举个例子现在我们要给所有指向外链的超链接加上跳转提示怎么做先写出用户调用的代码$(#main a).external();然后按照上面的方法编写一个external扩展$.fn.external function () {//return返回的each()返回结果支持链式调用return this.filter(a).each(function () {//注意each()内部的回调函数的this绑定为DOM本身var a $(this);var url a.attr(href);if(url (url.indexOf(http://)0 || url.indexOf(https://)0)){a.attr(href, #0).removeAttr(target).append().click(function () {if(confirm(你确定要前往 url ?)) {window.open(url);}});}});}对如下的HTML结构如何学习jQuery首先你要学习JavaScript并了解基本的HTML。实测外链效果use strict;$(#test-external a).external();小结扩展jQuery对象的功能十分简单但是我们要遵循jQuery的原则编写的扩展方法能支持链式调用、具备默认值和过滤特定元素使得扩展方法看上去和jQuery本身的方法没有什么区别。