第十七章:jQuery类库
javascript的核心API设计的很简单,但由于浏览器之间的不兼容性,导致客户端的API过于复杂。IE9的到来缓解了这种情况。然而使用javascript的框架或者工具类库,能简化通用操作,处理浏览器之间的差异,这让很多程序员在开发web应用时变得更简单。
jQuery类库被广泛的使用,作为web开发者,我们必须熟悉它:即便没有在自己的代码中遇到,也可能在别人的代码中遇见。幸运的是,jQuery代码足够小巧和稳定,本章就能将它讲述清楚。
jQuery能让你在文档中轻松找到关心的元素,并对这些元素进行操作:添加内容、编辑HTML属性和css属性、定义事件处理程序,以及执行动画。它还拥有Ajax工具来动态发起HTTP请求,以及一些通用的工具函数来操作对象和数组。
正如其名,jQuery类库聚焦于查询。一个典型的查询使用CSS选择器来识别一组文档元素,并返回一个对象来表示这些元素。返回的对象提供了大量的方法来批量操作匹配的元素。这些方法会尽可能返回调用对象本身,这使得简洁的链式调用成为可能。jQuery如此强大和好用,关键得益于以下特性:
- 丰富强大的语法(CSS选择器),用来查询文档
- 高效的查询方法,用来找到与CSS选择器匹配的文档元素集
- 一套有用的方法,用来操作选中的元素
- 强大的函数式编程技巧,用来批量材质元素集,而不是每次只操作单个
- 简洁的语言语法(链式调用),用来表示一系列顺序操作
本章首先会介绍如何使用jQuery来实现 简单的查询并操作其结果。接下来的章节会讲解:
- 如何设置HTML属性,CSS样式和类、HTML表单的值和元素内容、位置高宽,以及数据
- 如何改变文档结构:对元素进行插入、替换、包装和删除操作
- 如何使用jQuery的跨浏览器事件模型
- 如何用jQuery来实现动画视觉效果
- jQuery的Ajax工具,如何使用脚本来发起HTTP请求
- jQuery的工具函数
- jQuery选择器的所有语法,以及如何使用jQuery的高级选择方法
- 如何使用和编写插件来对jQuery进行扩展
- jQuery UI类库
1.jQuery基础
jQuery类库定义了一个全局函数:jQuery()。该函数使用频繁,因此在 类库中还给它定义了一个别名:$,这是jQuery在全局命名空间中定义的唯一两个变量。(如果你在自己的代码中有使用$作为变量,或者引入了Prototype等使用$作为全局变量的类库,这时,为了避免冲突,可以使用jQuery.noConflict()来释放$变量,让其指向原始值。)
这个拥有两个名字的全局方法是jQuery的核心查询方法,例如下面的代码能获取jQuery文档中的所有<div>元素:
var divs = $("div")
改方法返回的值表达零个或多个DOM元素,这就是jQuery对象。注意:jQuery()是工厂函数,不是构造函数,它返回一个新创建的对象,但并没有和new关键字一起使用。jQuery对象定义了很多方法,可以用来操作它们表示这组元素,本章中的大部分文字来阐述这些方法。例如:下面的这组代码用来找到拥有details类的p元素,将其高亮显示,并将其中隐藏的p元素快速显示出来。
$("p.details").css("background-color","yellow").show("fast");
上面的css()方法调用操作的jQuery对象是由$()返回的,css()方法返回的这个也是这个对象,因此可以继续调用show()方法,这就是链式调用,很简洁紧凑。在jQuery编程中,链式调用这个习惯用语很普遍。再举个例子,下面的代码可以找到文档中拥有"clicktohide"CSS类的所有元素,并给每一个元素都注册一个事件处理函数。当用户单击元素时,会调用事件处理程序,使得元素缓慢向上收缩,最终消失。
$(".clicktohide").click(function(){$(this).slideUp("slow");});
i.jQuery()函数
在jQuery类库中,最重要的方法是jQuery()方法,(也就是$())。它的功能很强大,有四种不同的调用方式。
第一种也是最常用的调用方式是传递CSS选择器(字符串)给$()方法。当通过这种方式调用时,$()方法会返回当前文档中匹配该选择器的元素集。jQuery支持大部分css3选择器语法,还支持一些自己的扩展语法。8小节i节将阐述jQuery选择器的语法。还可以将一个元素或jQuery对象作为第二个参数传递给$()方法,这时返回的是该特定元素或元素的子元素中匹配选择器的部分。第二个参数是可选的,定义了元素的查询的起点,经常称为上下文(context)。
第二种调用方式是传递一个Element、Document或window对象给$()方法。在这种情况下,$()方法只须简单地将Element、Document或window对象封装成jQuery对象并返回。这样可以使得能用jQuery方法来操作这些元素而不使用原生的DOM方法。例如,在jQuery程序中,经常可以看见$(document)或$(this)。jQuery对象可以表示文档中多个元素,也可以传递一个元素数组给$()方法。在这种情况下,返回的jQuery对象表示该数组中的元素集。
第三种调用方式是传递HTML文本字符串给$()方法。这这种情况下,jQuery会根据传入的文本创建好HTML元素并封装为jQuery对象返回。jQuery不会将刚创建的元素自动插入文档中,可以使用第3节描述的jQuery方法将元素插入到想要的地方。注意,在这种调用下,不可传入纯文本,因为jQuery会把纯文本当做是CSS选择器来解析。当使用这种调运风格时,传递给$()字符串必须至少包含一个带尖括号的HTML标签。
通过第三种方式调用时,$()接受可选的第二参数。可以传递Document对象来指定与所创建关联的文档。(比如,当创建的元素要插入iframe里时,需要显式的指定iframe的对象。)第二参数还可以是object对象。此时。假设该对象的属性表示HTML属性的键/值对,这些属性将设置到所创建的对象上。当第二参数对象的属性名是css,html,text,width,heigeht,offset,val,data或者属性名是jQuery事件处理程序注册方法名时,jQuery将调用新创建元素上的同名方法,并传入属性值。(css(),html(),text()等方法将在第2节讲述,事件处理程序注册方法将在第4节讲述),例如:
var img = $("<img>", //新建一个<img>元素 { src: url, //具有html属性 css: {borderWidth: 5}, //css样式 click: handClick //和事件处理程序 });
第四种调用方式是传入一个函数给$()方法。此时,当文档加载完且DOM程序可以操作时,传入函数将被调用。这是常见onLoad()函数的jQuery版本。在jQuery程序中,在jQuery()里定义一个匿名函数非常常见:
jQuery(function(){//文档加载完毕时调用 //所有的代码放在这里 });
有时候我们还可以看见老式的写法$(f)和完整的写法
$(document).ready(f)
传递给jQuery()的函数在被调用时,this指向document对象,唯一的的参数指向jQuery函数 。这意味这可以释放全局的$()函数,但在内部依旧可以延续该习惯:
jQuery.noConflict();//还原$()为初始值 jQuery(function($){ //让$()成为jQuery对象的局部别名 //jQuery代码 });
通过$注册的函数将在DOMContentLoaded事件触发时由jQuery触发。当浏览器不支持该事件时,会在load事件触发时由jquery触发。这意味这文档已经完毕,但图片等外部资源还有可能未加载完。如果DOM准备就绪后再传递函数给$(),传递的函数会在$()返回之前立刻调用。
jQuery类库还使用jQuery()函数作为其命名空间,在下面定义了不少的工具函数和属性。比如jQuery.noConflict();就是其中的一个工具函数。还包括遍历的jQuery.each(),以及用来解析JSON文本的jQuery.parseJSON()。第7节例举了这些通用函数,jQuery的其它函数在本章中都会提及。
jQuery术语
在本章中会提到一些重要的术语和短语,我们来看下其定义
jQuery对象:
jQuery函数是jQuery或$()的值。该函数可以用来创建jQuery对象,用来注册DOM就绪时需要调用的处理程序,还用做jQuery命名空间。我们常用$()来引用它。它可以用来做命名空间,因此,jQuery函数也可称为"全局jQuery对象",但要千万注意,不要把它和"jQuery对象"混淆。
jQuery对象
jQuery对象是由jQuery函数返回的对象。一个jQuery对象表示一组文档元素,也叫“jQuery结果”,“jQuery集”或“包装集”。
jQuery函数
jQuery函数是指定义在jQuery命名空间中的函数,比如jQuery.noConflict()。jQuery函数也称为“静态方法”。
jQuery方法
jQuery方法是由jQuery函数返回的jQuery对象的方法。jQuery类库最重要的部分就是它定义的这些强大的方法,
jQuery函数和jQuery方法有时很难区分,因此有部分函数和方法的名称是一样的:注意以下两行代码的差异:
//jQuery的each()函数用来对数组a中的每一个元素都调用一次函数f $.each(a,f); //调用jQuery()函数获取表示文档中所有<a>元素的jQuery对象 //然后调用该jQuery对象的each()方法,对选中的每一个元素调用一次函数f $("a").each(f)
ii.查询与查询结果
传递css选择器字符串给$(),它返回的jQuery对象表示匹配(或称为“选中”)的元素集。css选择器在13.2.iiiii介绍过
$()返回值是一个jQuery对象,jQuery对象是类数组,它们拥有length属性和介于0~length-1之间的数值属性。(7章11节有更多类数组对象的信息),这意味着可以使用标准的数组标识方括号来访问jQuery对象的内容。
$("body").length //=>1 文档只要一个唯一的body元素 $("body")[0] //等于document.body
如果不想把数组标识用来jQuery对象上,可以使用size()方法来替代length属性,用get()方法来代替方括号索引。可以使用toArray方法来讲jQuery对象转化为真实数组。
除了length属性,jQuery对象还有三个挺有趣的属性。selector属性是创建jQuery对象时选择器字符串(如果有的话)、context属性是上下文对象,是传递给$()方法第二参数,如果没有,默认是Document对象。最后,所有jQuery对象都在一个名为jquery的属性,检测改属性是否存在可以简单便捷地将jQuery对象与其他类数组对象区分开来。jQuery属性值是字符串形式的jQuery版本号
//获取document body中的所有<script>元素 var bodyscript = $("script",document.body); bodyscript.selector;//=>script bodyscript.context; //=>document.body bodyscript.jquery;//=> "1.8.3"
$()与querySelectorAll()
$()函数与13章2节iiiii节描述的Document对象的querySelectorAll()方法类似:两者都有css选择器作为参数,并且返回类数组对象来存放匹配选择器的元素。在支持querySelectorAll()的浏览器中,jQuery实现调用会调用querySelectorAll()方法,然而,在代码中使用$()代替querySelectorAll()依旧是很好的选择:
- querySelectorAll()在新近的浏览器中才实现能,$()在新老浏览器中都能跟踪
- jQuery可以通过手动实现选择,因此$()支持的css3选择器在所有的浏览器中,而不是支持css3的浏览器
- $()返回类 数组对象(Jquery对象),吧querySlectctorAll()返回的类数组对象(NodeList)更加有用
想要遍历jQuery对象中的所有元素时,可以调用each()方法来代替for循环,each()方法有点类似ECMAScript5(ES5)中的forEach()数组方法。它接受一个回调函数作为唯一的参数,然后对jQuery对象的中每一个元素(按照文档中的顺序)调用回调函数。回调函数作为匹配元素的方法来调用,因此,在回调函数里this关键字指代Element对象。
each()方法还会将索引值和该元素作为第一个和第二个参数传递给回调函数。注意:this和第二参数都是原生文档元素,而不是jQuery对象;如果想使用jQuery方法来操作该元素,需要先用$()封装它。
jQuery的each()方法和forEach()有一个显著的区别:如果回调函数在任一个元素上返回false,遍历将在该元素中止(就像在普通循环中使用break关键字一样)。each()返回调用自身的jQuery对象,因此它可以用于链式调用。下面这个例子(使用prepend方法将在第三小节阐述):
//给文档中的div元素标号,从开始一直到div#last(包含边界值) $("div").each(function(idx){//找到div元素,然后遍历它们 $(this).prepend(idx + ":");//找到没一个元素前面插入索引值 if(this.id === "last") return false;//碰到#last元素时终止 });
尽管each()方法很强大,但是用的并不多,因为jQuery方法通常隐式遍历匹配元素集并操作它们。需要使用到each()的典型场景需要不同的方式操作匹配的元素集并操作它们。需要使用each()的典型场景是需要不同的方式来操作匹配的元素。即便如此,也不需要调用each(),因为jQuery的一些方法允许传递回调函数。
在ECMAScript数组方法规范之前,jQuery类库就已经存在了。jQuery定义了几个方法,其功能和ECMAscript5方法功能类似。jQuery的map()方法和Array.prototype.map()的方法很相近。
它接受回调函数作为参数,并为jQuery对象中的没一个元素都调用回调函数,同时将回调函数的返回值收集起来,并将这些返回值封装成一个新的jQuery对象返回。map()调用回调函数的方式和each()方法相同:元素作为this值和第二参数传入,元素的索引值作为第一参数传入。如果回调函数返回null或undefined,该值将被忽略,在本次调用中不会有任何新元素添加到新的jQuery对象中。如果回调函数返回数组或类数组对象(比如jQuery对象),将会扁平化它并将其中的元素一个个添加到新的jQuery对象中。注意:由map()返回的jQuery对象可以不包含文档元素,但它依旧可以像类数组对象一样使用:例如
//找到所有标题元素,映射到它们的id,并转化为真实数组,然后排序 $(":header").map(function(){return this.id;}).toArray().sort();
除了each()和map()之外,jQuery的另外一个基础方法是index()。该方法接受一个元素作为参数,返回值是该元素在此jQuery对象中的索引值,如果找不到的话,则返回-1。显然,受jQuery的典型风格影响,index()方法有多个重载版本。传递一个jQuery对象作为参数,index()方法会对该对象的第一个元素进行搜索。如果传入的是字符串,index()会把它当成css选择器,并返回该jQuery对象中匹配该选择器的一组元素中的第一个元素的索引值。如果什么参数都不传入,index()方法返回该jQuery对象中第一个毗邻元素的索引值。
这里要讨论的最后一个通用的jQuery方法是is()。它接收一个选择器作为参数,如果选中元素中至少有一个匹配该选择器时,则返回true。可以在each()回调函数中使用它,例如:
if($(this).is(":hidden")) return;//跳过隐藏元素 //对可见元素做点什么 });
2.jQuery的getter和setter
jQuery对象上最简单、最常见的操作是获取(get)或设置(set)HTML属性、css样式、元素内容和位置高宽的值。该节讲述这些方法。首先,让我们对jQuery中的getter和setter方法有个概要理解。
- jQuery使用同一个方法即当getter又做setter用,而不是定义一对方法。如果传入一个新值给该方法,则它设置此值;如果没有指定值,则它返回当前值。
- 用做setter时,这些方法会给jQuery对象中的每一个元素设置值,然后返回该jQuery对象以方便链式调用。
- 用做getter时,这些方法只会查询元素集中的第一个元素,返回单个值。(如果要遍历所有元素,请使用map()。)getter不会返回调用自身的jQuery对象,因此它只能出现在链式调用的末尾。
- 用做setter时,这些方法经常接受对象参数。在这种情形下,该对象的每一个属性都指定一个需要设置的名/值 对。
- 用做setter时,这些方法经常接受函数参数。在这种情况下,会调用该函数来计算需要设置的值。调用该函数时的this值是对应的元素,第一个参数是该元素的索引值, 当前值则作为第二个参数传入。
在阅读本节接下来的内容时,请将对getter和setter的概要要理解牢记于心。下面的每一节会讲述jQuery getter/setter方法中的一个重要类别
i.获取和设置HTML属性
attr()方法是jQuery中用于HTML属性的getter/setter,它符合上面描述的概要和理解中的每一条。attr()处理浏览器的兼容性和一些特殊情况,还让html属性名和javascript属性名可以等同使用(当二者存在差异时)例如,可以使用"for"也可以使用"htmlFor",可以使用"class"也可以使用"className".一个相关函数是removeAttr(),可用来从所有选中元素中移除某个属性。下面是一些例子:
$("form").attr("action"); $("#icon").attr("src", "ico.gif"); //设置src属性 $("#banner").attr({ //一次性设置4个属性 src: "banner,gif", alt: "advertisenment", width: 720, height: 64 }); $("a").attr("target","_blank");//使所有链接在新窗口打开 $("a").attr("target",function(){ //非站内的链接在新窗口中打开 if(this.host == location.host) return "_self" else return "_blank"; }); $("a").attr({target:function(){...}}); //可以像这样传入函数 $("a").removeAttr("target");//
ii.获取和设置CSS属性
css()方法和attr()方法很类似, 只是css()方法作用于元素的css样式,而不是元素的HTML属性。在获取元素样式值时,css()返回的是当前样式,而不是元素的HTML属性。在获取样式值时,css()返回的是当前样式(或称为“计算”样式,参考14章4节):返回值可能来自style属性也可能来自样式表,注意:不能获取复合样式的值,比如:font或margin。而获取单个样式的值,font-weiht、margin-top等、
在设置样式时,css()方法会将样式简单添加到元素的style属性中。css()方法允许在CSS样式名中使用联系的字符串("background-color")或使用驼峰式javascript样式名("backgroundColor")。在获取样式值时,css()会把数值转换为带有点位的后缀字符串返回。而在设置样式值时,则会将数值转化为字符串,在必要的时候添加"px"等单位后缀。
$("h1").css("font-weight"); $("h1").css("font-size"); $("h1").css("font"); //错误,不能获取复合样式的css属性 $("h1").css("font-variant", "small-caps"); //该属性主要用于定义小型大写字母文本 $("div").css("border", "solid black 2px"); //这样设置复合属性是没问题的 $("h1").css({ backgroundColor: "black", //一次性设置多个样式 color: "white" }); //让所有的<h1>字体大小增加25% $("h1").css("font-size", function(i, curval) { return Math.round(1.25 * parseInt(curval)); });
iii.获取和设置css类
回忆一下,class属性值(在javascript里通过className访问)会被解析称为一个由空格风格的CSS类名列表。通常,我们想要往列表中添加、删除某一项,或判断某一想是否在列表中,而不是将该列表替换为另一个。因此,jQuery定义了一些便捷方法来操作class属性。addClass()和removeClass()用来从选中元素中添加和删除类。toggleClass()的用途是,当元素还没有某些类时,给元素添加这些类,反之,则删除。hasClass()用来判断某类是否存在,下面是一些例子:
//添加css类 $("h1").addClass("hilite"); //给所有的h1添加一个class $("h1+p").addClass("hilite firest"); //给h1后面的p添加两个类 $("section").addClass(function(n){ //传递一个元素添加自定义类 return "section" + n; //每个元素添加自定义类 }); //删除CSS类 $("p").removeClass("hilite");//从所有p元素中删除一个类 $("p").removeClass("hilite first");//一次性删除多个类 $("section").removeClass(function(n){ //删除元素中自定义的类 return "section" + n; }); $("div").removeClass(); //删除所有<div>中的所有类 //切换CSS类 $("tr:odd").toggleClass("oddrow");//如果该类不存在则添加 //存在则删除 $("h1").toggleClass("big samll"); //一次切换两个类 $("h1").toggleClass(function(n){ //切换函数计算出来的类 return "big bold h1-" +n; }); $("h1").toggleClass("hilite",true); //作用类似addClass $("h1").toggleClass("hilite",false); //作用类似removeClass //检测css类 $("p").hasClass("first"); //是否所有p元素都有该类? $("#lead").is(".first"); //功能和上面类似 $("#lead").is(".first.hilite"); //is()比hasClass()更灵活
注意:hasClass()不如addClass()、removeClass()、toggleClass()灵活。hasClass()只能接受单个类名作为参数,并且不支持函数参数。当选中元素中任意元素有指定的CSS类时,HasClass()返回true;如果什么元素都没有,则返回false,上面的is()方法更灵活,可以做同样的事情。
jQuery的这些方法和14章5节的classList方法类似,只是jQuery方法可以工作在所有的浏览器中,而不是支持css3的浏览器。此外,毫无疑问jQuery的方法可以操作多个元素并支持链式调用。
iiii.获取和设置HTML表单值
val()方法用来设置和获取HTML表单元素的value属性,还可以用于获取和设置复选框、单选按钮以及<select>元素的选中状态。
$("#surname").val(); //获取surname 文本域的值 $("#usstate").val(); //从<select>中选取单一值 $("select#extras").val(); //从<select multiple>中获取一组值 $("input:radio[name=ship]:checked").val(); //获取单选选中按钮的值 $("#email").val("invalid email address"); //给文本域设置值 $("input:checkbox").val(["op1","op2"]) //选中带有这些名字或值的复选框 $("input:text").val(function(){//重置所有文本域为默认值 return this.defaultValue; });
iiiii.设置和获取元素内容
text()和html()方法用来获取和设置元素的纯文本或HTML内容。当不带参数调用时,text()返回所有匹配元素的所有子孙文本节点的纯文本内容。该方法甚至可以发展在不支持textContent或innerText属性(13章5节ii)的浏览器中。
如果不带参数调用html()方法,它会返回第一个匹配元素的HTML内容。jQuery使用innerHTML属性来实现:x.html()和x[0].innerHTML一样高效
如果传入字符串给text()或html(),该字符串会用做该元素的纯文本或格式化的html文本内容,它会替换掉所有存在的内容。和其他setter方法一样,我们还可以传入函数,此函数用来计算表示新内容的字符串:
var title = $("head title").text(); //获取文本标题 var headline = $("h1").html(); //获取第一个<h1>元素的HTML $("h1").text(function(n,current){//给每一个标题添加章节号 return "§" + (n+1) + ":" + current });
iiiiii.获取和设置元素的位置高宽
在13章8节中我们知道通过一些技巧可以正确获取元素的大小和位置,尤其当浏览器不支持getBoundClientRect(13章8节ii)时,使用jQuery方法可以更简单的获取元素的大小和位置,并兼容所有浏览器。注意:本节描述的所有方法都是getter,只有少部分可以用作setter。
使用offset()方法可以获取或设置元素的位置 。该方法相对文档来计算位置值,返回一个对象,带有left和top属性,用来表示x和y坐标。如果传入带有这些属性的对象给该方法,它会给元素设置指定的位置。在有必要时,会设置CSS的position属性来是的元素可定位:
var elt = $("#sprite"); //选择要移动的元素 var position = elt.offset(); //获取当前元素的位置 position.top += 100; //改变y坐标 elt.offset(position); //从新设置位置 //将所有的<h1>元素向右移动,移动的距离取决于他们在文档中的位置 $("h1").offset(function(index, curpos) { return { left: curpos.left + 25 * index, top: curpos.top }; });
postion()方法很像offset()方法,但它只能用作getter,它返回的元素位置是相对于其偏移父元素的,而不是相对文档的。在13章8节iiiii中,我们知道任何一个元素都有一个offsetParent属性,其位置是相对的。定位元素总会当做其子孙元素的偏移父元素,但在某些浏览器下,也会把表格单元格等其他元素当成偏移父元素。jQuery只会把定位元素作为偏移父元素。jQuery对象的offsetParent()方法则会把每个元素的映射到最近的定位祖先元素或<body>元素。注意这些方法的名字并不很恰当:offset()返回元素的绝对位置,相对于文档的坐标来表示。而postion()则返回相对元素的offsetParent()的偏移量。
对于获取元素的宽度的getter有3个,获取的高度也有3个。
width()和height()方法返回基本的宽度和高度,不包含内边距 、边框和外边距。
innerWidth()和innerHeight()返回元素的宽度和高度,包含内边距的宽度和高度(“内”表示这些方法度量的是边框以内的尺寸)。
outerWidth()和outerHeight()通常返回的是包含元素内边距和边框的尺寸。如果向两个方法中任意一个传入true值,他们还可以返回包含元素外边距的尺寸。下面代码展现了如何获取一个元素的4种不同宽度:
var body = $("body"); var contenetWidth = body.width(); var paddingWidth = body.innerWidth(); var borderWidth = body.outerWidth(); var marginWidth = body.outerWidth(true); var padding = paddingWidth - contenetWidth; //左内边距和右内边距的和 var borders = borderWidth - paddingWidth; //左边框和右边框的和 var margins = marginWidth - borderWidth; //左外边距和右边距的和
width()和height()方法拥有其它4个方法(以inner和outer开头的方法)所没有的特性,首先,当jQuery对象的第一个元素是Window或Document对象时,width()和height()返回的是窗口的视口大小或文档的整体尺寸。其它方法只适用于元素,不适合窗口和文档。
另一个特性是width()和height()方法可以是setter()也可以是getter()。如果传递值给这些方法,他们会给jQuery对象中的每一个元素设置宽度或高度。(注意:不能给window和document对象对象设置宽度或高度。)如果要传入数值,会把它当成单位为像素的尺寸。如果传入字符串,会把它用作css的width和height属性的值,因此可以使用任何css单位。最后,和其他setter类似 ,可以传入函数,用来计算要设置的宽度或高度。
在width()和height()的getter和setter行为之间有个小的不对称。用作getter时,这些方法返回元素的内容盒子尺寸,不包括内边距、边框和外边距。用做setter()时,他们只是简单的设置CSS的width和height属性。默认的情况下,这些属性也指定内容盒子的大小。但是,如果一个元素的CSS box-szing属性(14.2.iii)设置为border-box,则width()和height()方法设置的尺寸包括内边距和边框。对于使用context-box作为盒模型的元素e,调用$(e).width(x).width()返回x值。然而,对于使用border-box模型的元素,这种情况下一般不会返回x值。
与位置尺寸相关的最后与对jQuery方法是scrollTop()和scrollLeft(),可获取或设置元素滚动条的位置。这些方法可以用在window对象以及Document元素上,当用在Document对象上时,会获取或设置存放改Document的window对象的滚动条位置。与其他setter不同,不可传递函数给scrollTop()和scrollLeft()。
可使用scrollTop()作为getter和setter,与height()方法一起,来定义一个方法:根据指定的页面数向上或向下滚动窗口
//根据页面数n来滚动窗口。 n可以是分数也或负数 function page(n){ var w = $(window); //将window封装为jQuery对象 var pagesize = w.height(); //得到页面大小 var current = w.scrollTop(); //得到当前滚动条的位置 w.scrollTop(current + n*pagesize);// 设置新的滚动条位置 }
iiiiiii.获取和设置元素数组
jQuery定义了一个名为data()的getter/setter方法 ,用来设置或获取与文档元素、Document或Window对象相关联的数据。可以将数据与任意元素关联是很重要和强大的一项能力:这是jQuery的事件处理程序注册和效果队列机制的基础,有时,我们还会再自己的代码中使用data()方法。
需要将数据与jQuery对象中的元素关联,传递名称和值两个参数给data()即可。还可以传递一个对象给data() setter,此时,该对象的每一个属性都将用做名/值对,用来与jQuery对象的元素关联。注意,传递对象给data()时,该对象的属性将替换掉与元素相关联的旧数据。其其它很多setter方法不同,data()不接受函数参数。当将函数作为第二参数传递给data()时,该函数会存储,就和其他值一样。
当然,data()方法也可以用做getter。当不带参数调用时,它会返回一个对象,含有与jQuery对象中的第一个元素相关联的所有名/值对。当传入一个字符串参数调用data()时,它会返回对已第一个元素与该字符串相关联的数据值。
removeData()方法从元素中删除数据。(使用data()设置值为null或undefined和实际上删除该值并不是同一回事。)如果传递字符串给removeData(),该方法会删除元素中与该字符串相关联的值。如果不带参数调用removeData(),它会删除与元素相关联的所有数据。
$("nodes").data("x",1);//设置一些数据 $("div.nodata").removeData("x"); //删除一些数据 var x = $(‘#nodes‘).data("x"); // 获取一些数据
jQuery还定义了data()和removeData()方法的工具函数形式。要给单一元素e关联数据,可以使用data()方法形式,也可以使用其函数形式:
$(e).data(...) //方法形式 $.data(e,...) //函数形式
jQuery的数据框架没有将元素数据当做元素的属性来存储,但它的确需要给元素添加一个特殊的属性来与数据关联。由于某些浏览器不允许添加属性到<applet>、<object>和<embed>元素中,因此,jQuery根本不允许给这些类型的元素关联数据。
3.修改文档结构
我们在2节iiiii节中我们知道html()和text()方法用来设置元素内容。本节将讲述能对文档做出更复杂的修改的方法。HTML文档表示为一棵节点树,而不是一个字符的线性序列,因此插入、删除、替换、操作不会像操作字符串和数组一样简单。接下来的内容会阐释用于文档修改的jQuery的各种方法。
i.插入和替换元素
让我们从基本的插入和替换方法开始。下面演示的每一个方法都接受一个参数,用于指定需要插入文档中的内容。该参数可以是用于指定新内容的纯文本或html字符串,也可以是jQuery对象、元素或文本节点。根据调用的方法不同,会在选中元素的里边,前面,或后面插入内容。如果待插入的内容是已存在于文档中的元素,会从当前的位置移走它。如果它需要插入多次,在必要的时会复制该元素。这些方法都返回自身的jQuery对象。注意,在replaceWith()运行后,该jQuery对象中的元素将不存在于文档中:
$("#log").append("<br/>" + message); //在#log元素结尾处添加内容 $("h1").prepend("§"); //在每个<h1>的起始处添加章节标识符 $("h1").before("<hr/>"); //在每个<h1>的前面添加水平线 $("h1").after("<hr/>"); //在每个<h1>的后面添加水平线 $("hr").replaceWith("<br/>") //将<hr/>元素替换为<br/> $("h2").each(function(){//将<h2>替换为<h1>,保持内容不变 var h2 = $(this); h2.replaceWith("<h1>" + h2.html() + "</h1>"); }); // after()和before()也可用在文本节点上 // 这是给每个<h1>的开头添加上章节标识符的另一种方法 $("h1").map(function(){ return this.firstChild; }).before("§")
这5个用于结果修改的方法都接受函数参数,原理啊计算出需要插入的值。和平常一样,如果传入参数,该函数会为每个选中的元素调用一次。this指向该元素,在jQuery对象中元素的索引值将作为第一参数。对于append()、prepend()个replaceWidth(),第二参数将是该元素当前内容的HTML()字符串形式。对于before()和after(),该函数在调用时没有第二参数。
上面演示的5个方法都在目标元素上调用,并传入需要插入的内容作为参数。这5个方法中的每一个都可以找到另一个方法来实现差不多一样的功能,只要采用不同的操作方式即可:在内容上调用,并传入目标元素作为参数。下面展示了这些方法对:
操作 | $(target).method(content) | $(content).method(target) |
在目标元素的结尾处插入内容 | append() | appendTo() |
在目标元素的起始处插入内容 | prepend() | preprendTo() |
在目标元素的后面插入内容 | after() | insertAfter() |
在目标元素的前面插入 内容 | before() | insertBefore() |
将目标元素替换为内容 | replaceWith() | replaceAll() |
想要理解这几个方法,有几个重要事项
如果传递字符串给第二列中的方法,会把它当做需要插入的HTML字符串。如果传递字符串给第三列中的方法,会把它当做选择器,用来标识目标元素。(也可以直接传入jQuery对象、元素或文本节点来指明目标元素)
第三列的方法不接受函数参数,第二栏中的方法可以。
第二列中的方法返回调用自身的jQuery对象。该jQuery对象中的元素有可能有新内容或新兄弟节点,但这些元素自身没有修改。第三列中的方法在插入的内容上调用,返回一个新的jQuery对象,表示插入操作后的新内容。特别注意,当内容被插入多个地方时,返回的jQuery对象将为每一个地方保留一个元素。
上面例举了不同点,下面的代码将实现与上面代码一样的操作,使用的是第三列的方法来替代第二列中的。注意在第二行中的代码不能传入纯文本(不带任何<>括号来标识它为HTML)给$()方法--它会被当做选择器。因此,必须显式创建需要插入的文本节点:
$("<br/> + message").appendTo("#log"); //添加html到#log中 $(document.createTextNode("§")).prependTo("h1"); //给所有<h1>添加文本节点 $("<hr/>").insertBefore("h1"); //在所有的<h1>前面插入水平线 $("<hr/>").insertAfter("h1"); //在所有的<h1>后面插入水平线 $("<br/>").replaceAll("hr"); //将<hr/>替换为<br/>
ii.复制元素
如上所述,如果插入的元素已经是文档的一部分,这些元素只会简单地移动而不是复制到新位置。如果元素到插入不止一个位置,jQuery在需要时会复制元素,但是当只插入一个位置时,是不会进行复制操作的。如果想复制元素到新位置而不是移动它,必须首先用clone()创建并返回每一个选中元素(包含元素所有子孙)的一个副本。clone()创建并返回一个选中元素(包含元素所有子孙)的一个副本。返回的jQuery对象的元素还不是文档的一部分,可以用上一节的方法将其插入文档中。
//给文档结尾添加一个带有"linklist" id的新div $(document.body).append("<div id = ‘linklist‘><h1>List of Links</h1></div>"); //将文档中所有链接复制并插入新div中 $("a").clone().appendTo("#linklist"); //在每一个链接后面插入<br/>元素,使其独立行显示 $("#linklist > a").after("<br/>");
clone()不会复制事件处理程序(见第4节)和与元素相关联的其它数据(2节iiiiiii)。如果想复制这些额外的数据,请传入true参数。
iii.包装元素
插入HTML文档的另一只类型涉及在一个或多个元素中包装新元素。jQuery定义了3个包装函数。wrap()包装每一个选择元素。wrapInner()包装每一个选中元素的内容。wrapAll()则将选中元素作为一组数组来包装。这些方法通常传入一个新创建的包装元素或用创建新包装元素的HTML字符串。如果需要,HTML字符串可以包含多个嵌套元素,但必须是单个最内层的元素。如果传入函数给这些方法,它会在每个元素的上下文中调用一次,this指向该元素,元素的索引值是唯一参数,应该返回需要返回表示包装元素的字符串、Element或jQuery对象。下面是些例子:
//用<i>元素包装所有<h1>元素 $("h1").wrap(document.createElement("i")); //=> <i><h1></h1></i> //包装所有<h1>元素的内容,使用字符串参数更简单 $("h1").wrapInner("<i/>") //=> <h1><i>1</i></h1> // 将第一个段落包装在一个锚点和div里 $("body>p:first").wrap("<a name=‘lead‘><div class=‘first‘></div></a>"); // 将所有其它段落包装在另一个div里 $("body>p:not(:first)").wrapAll("<div class=‘rest‘></div>");
iiii.删除元素
除了插入和替换操作,jQuery还定义了用来删除元素的方法。empty()会删除每个选中元素的所有子节点(包括文本节点),但不会修改元素自身。对比而言,remove()方法会从文档中移除选中元素(以及 元素的所有的 内容。)通常不带参数调用remove(),此时会从文档中移除jQuery对象中的所有元素。然而,如果传入一个参数,该参数会被当成选择器,jQuery对象中只有匹配该选择器的元素才会被移除。(如果只想将元素从选中元素集中移除,而不需要从文档中移除时,请使用filter()方法,该方法会在8.ii中讲述)注意,将元素重新插入文档钱,移除操作是没必要的:简单地将其插入新的位置,就会移除他们。
remove()方法会移除所有的时间处理程序(参加4节)以及绑定到元素上的其它数据(2.iiiiiii)。detach()方法和remove()类似,但不会移除事件处理程序和数据。想临时从文档中移除元素以便后续再插入时,detach()可能会更有用。
最后,unwarp()方法可以用来实现元素的移除,其方式是wrap()或wrapAll()方法的反操作:移除每一个选中元素的父元素,不影响选中元素及兄弟节点。也就是说,对于每一个选中的父元素,它替换改元素的父节点为父节点的子节点。与remove()和detach()不同,unwrap()不接受可选的选择器参数。
(本文未完结,稍后更新)
4.使用jQuery处理事件
5.动画效果
6.jQuery中的ajax
7.工具函数
8.jQuery选择器和选取方法
9.jQuery的插件扩展
10.jQuery ui类库
上一章:第十六章:脚本化HTTP 下一章:第十八章:客户端存储
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。