我要以个人的名义感谢 Brandon Aaron, Ben Alman, Louis-Rémi Babe, Ariel Flesler, Paul Irish, Robert Kati?, Yehuda Katz, Dave Methvin, Justin Meyer, Karl Swedberg, and Aaron Quint。谢谢他们在修复BUG和完成这次发布上所做的工作
下载(Downloading)
按照惯例,我们提供了两份jQuery的拷贝,一份是最小化的(我们现在采用Google Closure作为默认的压缩工具了),一份是未压缩的(供纠错或阅读)。
jQuery 压缩 (23kbGzipped)
(154kb)
另外,Google也在他们的服务器上放置了一份jQuery的拷贝。这份拷贝会自动的最小化然后压缩 – 并且放在Google最快的缓存服务器上。
http://code.google.com/apis/ajaxlibs/documentation/index.html
你可以在你的站点上直接引用上面的URL,这样就可以享受迅速加载jQuery的性能优势了。
就jQuery1.4来说,我们努力的减少大规模升级中的麻烦 – 通过保持所有public函数的签名。即使如此,还请下面可能会造成问题的变更列表,这样能够了解哪些变更可能会给你的应用造成问题。
(功能) Features
下面的内容概括了jQuery1.4里加入的变更和功能。另外所有的变更都已经在jQuery 1.4 的文档里记录了。
热门方法经过了性能上的大”检修”
不少比较热门的和常用的jQuery方法在1.4里被重写了。(译注:重写了方法的内部,外部调用没有大幅度改变) 我们分析源码的时候发现我们能够获得大幅的性能提升,通过把jQuery和自己比较: 查看内部函数被调用了多少次,然后努力降低 源码的复杂度(译注:计算机算法中的Complexity)
在1.4版里我们显著的降低了大部分热门jQuery方法的的复杂度。
更易用的设置函数 (Easy Setter Functions)
算来已经有一阵了,你们已经可以给.attr()传 递一个函数,然后这个函数的结果会被用来赋给相应的html属 性(attribute)上。这个功能现在被移植到所有的设置函数了: .css(), .attr(), .val(), .html(), .text(), .append(), .prepend(), .before(), .after(), .replaceWith(), .wrap(), .wrapInner(), .offset(), .addClass(), .removeClass(), 以及 .toggleClass().
另外, 对于下面几个方法,当前的值会被作为第2个变量传递给这个函数。.css(), .attr(), .val(), .html(), .text(), .append(), .prepend(), .offset(), .addClass(), .removeClass(), 以及 .toggleClass().
这样代码就可以这样写:
// 找出所有A标签里的'&'字符,然后用一个span标签包围 $('a').html(function(i,html){ return html.replace(/&/gi,'&'); }); // 给一些链接的title属性加些信息 $('a[target]').attr("title", function(i,title){ return title + " (新窗口打开)"; });
ajax
嵌套参数的序列化 (jQuery.param() 文档, Commit 1, Commit 2)
jQuery 1.4在jQuery.param方法里加入了嵌入参数序列化的支持,借用了PHP编程里兴起的,而后又被Ruby on Rails推广开来的方式。
举例来说,
{foo: ["bar", "baz">} 会被序列化为 “foo[>=bar&foo[>=baz”.
在jQuery 1.3版里, {foo: ["bar", "baz">} 曾被序列化为 “foo=bar&foo=baz”. 但是,这样做没用办法将只含有一个元素的阵列编码。如果你需要旧的序列化方式,你可以设置传统Ajax 设置来进行切换。(使用 jQuery.ajaxSettings.traditional进行全局切换,或者根据情况单独切换。
总共有3种方式可以切换到旧的序列化方式:
// 全局改变序列化方式 (使用旧的) jQuery.ajaxSettings.traditional = true; // 指定情况使用旧的序列化方式 jQuery.param( stuff, true ); // 针对一个单独的Ajax请求使用旧的序列化方式 $.ajax({ data: stuff, traditional: true });
更多信息参见: jQuery.param() 文档, jQuery.ajax() 文档, Commit, Code
JSON和脚本类型通过”content-type”自动识别。 (jQuery.ajax 文档, Commit 1, Commit 2)
如果一个Ajax请求的回复的媒体类型是JSON(application/json), dataType默认设为”json”(如果 dataType没有被指明)。另外,如果回复的媒体类型是 Javascript(application/javascript), dataType默认设为”script”(同样,如果 dataType没有明确指明), 这种情况下,脚本会自动运行。
加入了Etag的支持 (jQuery.ajax() 文档, Commit)
默认设置下, jQuery会忽略Ajax请求的”Last-Modified”页头。这样做是为了忽略浏览器的缓存。设置 ifModified:true就可以使 jQuery使用可用的缓存。jQuery1.4还会发出”If-None-Match”的页头如果你设置了 ifModified选项。
严格JSON模式,本地的JSON.parse方法 (jQuery.ajax() 文档, Commit 1, Commit 2, Commit 3)
jQuery 1.3和以前的版本曾使用Javascript的eval对引入的JSON解析。1.4版则会使用本地的JSON解析器,前提是如果有本地的解析器可用。 它也会对引入的JSON进行校验。所以在jQuery.getJSON方法里,或当一个Ajax请求的dataType是”json”的时 候,jQuery会拒绝不合标准的JSON(例如{foo: "bar"})。
序列化HTML5的元素 (jQuery.param() 文档, Commit)
新的HTML5输入方法 (比如’datetime’和’range’)在序列化.serialize()一 个表单的时候会被包括在内。
Ajax请求的环境 (jQuery.ajax() 文档, Commit)
你可以附加一个”环境”到Ajax请求上,所有的回调函数里都会拥有同样的”环境”设置(这样可以简化你的代码,尽可能避免使用闭合,或是其他对 象)。
jQuery.ajax({
url: "test.html",
context: document.body,
success: function(){
jQuery(this).addClass("done");
}
});
请求成功回调函数的第三个参数会被设为原始的XHR对象 (jQuery.ajax() 文档, Commit)
所有的Ajax请求的成功回调函数现在都会收到原始的XMLHttpRequest对象,作为第三个参数。之前这个XHR对象只能通过$.ajax 一类方法的返回值来获取。
明确设置”Content-Type” (jQuery.ajax() 文档, Commit)
在1.3版,如果没有实际数据发送,jQuery.ajax的 contentType会被忽略。1.4版里,contentType将总是和请求一 同发送。这修复了某些后台凭靠”Content-Type”页头判断回复类别所造成的问题。
明确设置 JSONP回调函数的名字 (jQuery.ajax 文档, Commit)
你可以使用jQuery.ajax()方 法的jsonpCallback选项,通过名字来指定JSONP的回调函数。
防止启动前跨域XHR (Commit)
跨域Ajax(针对提供支持的浏览器)将更易用,因为默认设置下,启动前XHR被阻止了。(TODO)
jQuery.ajax() 现在使用”onreadystatechange”事件替换了计时器 (Commit)
使用”onreadystatechange”替换了轮流探询,Ajax请求现在将使用更少的资源
元素属性 (Attributes)
.CSS()和.attr() 的性能被优化了。
.attr()方法多了一个设置函数作为参数 (.attr() 文档)
你不但可以将一个函数用在.attr()里,还可以在这个函数里使用属性的当前值。
jQuery('<img xsrc="enter.png" alt="enter your name" />')
.attr("alt", function(index, value) {
return "Please, " + value;
});
.val( Function ) (.val() 文档)
<input class="food" type='text' data-index="0" /> <input class="food" type='text' data-index="1" />
jQuery("input:text.food").hide();
jQuery("<ul class='sortable'><li>Peanut Butter</li><li>Jelly</li></ul>"
)
.sortable()
.bind("endsort", function() {
$(":text.food").val(function() {
return $("ul.sortable li:eq(" + $(this).attr("data-index") + ")").text();
});
});
text和CDATAHTML元素也支持.text()方法了 (.text() 文档, Commit)
核心 (Core)
快捷元素创建 (jQuery() 文档, Commit)
现在当你需要使用jQuery函数创建一个元素的时候,你可以同时附递一个对象来指定属性值和事件:
jQuery("
", {
id: "foo",
css: {
height: "50px",
width: "50px",
color: "blue",
backgroundColor: "#ccc"
},
click: function() {
$(this).css("backgroundColor", "red");
}
}).appendTo("body");
对象里的键值的名字与相关的jQuery的方法的名字是对应的,对象的值会被作为参数传递给jQuery的方法。
(译注:譬如$("<a>link</a>", {css:{background:"#ccc"}});相当 于$("<a>link</a>")).css("background", "#ccc");
.eq(-N), .get(-N) (负指数) (.eq() 文档, .get() 文档, Commit)
你现在可以在.get()和.eq()方法里使用负数。譬如,你要选择倒数第2个div元素,或者是倒数第2个DOM对象:
$("div").eq(-2);
样式 (CSS)
.css()方法在性能是以前的2倍。
.addClass(), .removeClass(), 和 .hasClass()这 几个方法在性能上是以前的3倍
.toggleClass()可以切换多个css类了 (.toggleClass() 文档, Commit)
你可以通过.toggleClass()调 用多个css类的名字来切换他们。
$("div").toggleClass("current active");
数据
.data()返回对象, .data(Object)设置对象 (.data() 文档, Commit 1, Commit 2)
有时候你可能需要在一个元素上附加一个复杂的对象。一个常见的例子是你需要从一个元素身上复制所有的数据到令一个元素上。在jQuery 1.4里, 不使用任何参数调用.data()时,.data 会返回一个复杂对象。(译注: 包含所有键-值对的对象。) 调用.data(Object) 则会设置这个对象。注意这个对象还包括了元素上绑定的事件,所以用的时候要小心。
除非需要, 不然不会创建数据缓存。 (Commit 1, Commit 2, Commit 3)
jQuery使用一个独特的自定义属性来获取特定元素上附加的数据。当查找数据,但是没有新加的数据的时候,jQuery会尽量避免创建这个自定义 属性。这样可能会提高性能,同时还会在这种情况下避免污染DOM。
效果 (Effects)
单个属性缓进缓出 (Per-property Easing 文档, Commit)
除了能够给一个动态效果指定缓进出函数外,你现在可以指定每个属性的缓进出函数了。James Padolsey的blog上有更进一步的信息和演示。
$("#clickme").click(function() {
$("div").animate({
width: ["+=200px", "swing"],
height: ["+=50px", "linear"],
}, 2000, function() {
$(this).after("<div>Animation complete.</div>");
});
});
事件 (Events)
新方法: jQuery.proxy() (jQuery.proxy() Documenation, Commit 1, Commit 2)
如果你需要保证一个函数内的”this”恒定地保持某个值, 你可以用jQuery.proxy获得一个相同作用域的函数。
var obj = {
name: "John",
test: function() {
alert( this.name );
$("#test").unbind("click", obj.test);
}
};
$("#test").click( jQuery.proxy( obj, "test" ) );
多个事件绑定 (.bind() 文档)
你可以通过递入一个对象来一次性绑定元素的多个事件。
$("div.test").bind({
click: function(){
$(this).addClass("active");
},
mouseenter: function(){
$(this).addClass("inside");
},
mouseleave: function(){
$(this).removeClass("inside");
}
});
‘change’和’submit’事件规范化 (Change 文档, Submit 文档)
普通的或是即时的change和submit事件可以在各种浏览器上稳定工作了。我们覆盖了IE里的change和submit, 替换为与其他浏览器相同的事件。
新的事件: ‘focusin’ and ‘focusout’ (.focusin() 文档, .focusout() 文档, Commit)
focusin和focusout在一般情况下等同于focus和blur, 但是多了向父元素传递的作用。如果你自己编写你的事件代理模式 (TODO), 这个功能将对你有很大帮助。请注意对focus和blur使用live()方法将不会起作用; 在设计的时候我们根 据 DOM事件规范决定不使其向父元素传递事件。
$("form").focusout(function(event) {
var tgt = event.target;
if (tgt.nodeName == "INPUT" && !tgt.value) {
$(tgt).after("nothing here");
}
});
所有的事件都可以成为即时事件 (.live() 文档)
除了ready, focus (用focusin), 和 blur (用focusout)以外, 所有能用.bind()绑定的事件都可以成为即时事件。
在live()所支持的事件里,我们对能够支持下面这几个额外的事件感到尤其骄傲。通过.live()里的事件代理, 1.4版实现了对change, submit, focusin, focusout, mouseenter, 以及mouseleave事件的跨浏览器支持。
注: 如果你需要即时的focus事件,你应该用focusin和focusout, 而不要用focus和blur, 因为就像前面提到的, focus和blur不向上传递。
还有, live()也接受数据对象作为参数了, 同bind()方法一样 (Commit)
live/die也支持环境变量了 (Commit)
现在可以在绑定事件的时候给选择符指定一个环境。如果环境被指定了, 只有属于这个环境下的元素才会被绑定事件。在创建即时事件的时候, 元素本身不需要已经被定义, 但是环境必须被创建。
确定ready事件至少含有body元素 (Commit)
jQuery现在会检查body是不是存在,如果不存在,会对body进行轮流探询。
在不需要手动处理内存溢出的非IE浏览器中, 卸载的速度提高了。 (Commit)
DOM操作 (Manipulation)
在jQuery 1.4里一系列的DOM操作方法的性能都有巨大的提升。
.append(), .prepend(), .before(), and .after()的性 能提高了。
.html()的 性能提高到以前的3倍。
.remove() 和.empty()的速度则达到以前的4倍.
新方法: .detach() (.detach() 文档, Commit)
detach()将一个元素从DOM里移除, 但是并不卸载关联的事件处理函数。这个方法可用于暂时性的将一个元素移除,执行相关操作,然后返回。
var foo = $("#foo").click(function() {
// 相关操作
});
foo.detach();
// foo保留了相关处理函数
foo.appendTo("body");
新的unwrap()方法 (documentation, commit)
unwrap()方法拿到一个已知的父元素的子元素,然后将父元素用子元素替换。(译注: 将子元素从”包裹”里拿出来, 因名unwrap)。如此这般:
<body>
<div>
<p>annie</p> <p>davey</p> <p>stevie</p>
</div>
</body>
$('div').unwrap();
<body>
<p>annie</p> <p>davey</p> <p>stevie</p>
</body>
domManip方法里的缓存 (commit)
jQuery会将jQuery("<div>")和.after("<div>")一类方法创建的节点记入缓存。这样, 对于利用这些方法, 使用字符串进行DOM操作的页面,性能将有极大的提高。
无连接的节点间的before, after, replaceWith操作 (commit)
现在你可以对还没有放置到DOM Tree上的节点进行before, after, 和replaceWith的操作了。意味着你可以先对节点进行复杂的操作, 待完成后再放到合适的DOM位置上。这样也能尽量避免操作过程中造成重新排版。
jQuery("<div>").before("<p>Hello</p>").appendTo("body")
.clone(true) 也会复制关联数据 (clone 文档, commit)
1.3版中, .clone(true)虽然也是深度复制, 但是没有复制关联的数据。1.4版里,它则会复制数据, 同时还包括所有的事件。这点上和jQuery.extend在语义想同的, 所以普通对象和阵列会被复制, 但是自定义的对象则不会。
位移 (Offset)
.offset( coords | Function ) (.offset() 文档, commit)
现在可以设置元素的位移了! 和所有的设置函数一样, offset也可以接受一个函数作为第二个参数。
队列 (Queueing)
队列经历了一次大修, 使用队列会比使用默认的fx更易掌握。
新的 .delay() 方法 (.delay() 文档, commit)
.delay()方法会根据参数滞后若干毫秒执行队列里剩下的对象。默认的它会使用”fx”队列。但你可以选择性的通过delay方法的第二个参数 选择其他队列。(译注:每个队列都以一个名字识别。)
$("div").fadeIn().delay(4000).fadeOut();
队列里的next (.queue() 文档, commit)
jQuery 1.4版里, 当队列里的一个函数被调用的时候,第一个参数会被设为另一个函数。当后者被调用的时候, 会自动排除队列里的下一个对象, 以此来推动队列到下一步。
jQuery("div").queue("ajax", function(next) {
var self = this;
jQuery.getJSON("/update", function(json) {
$(self).html(json.text);
next();
};
}).queue("ajax", function() {
$(this).fadeIn();
});
.clearQueue() (clearQueue 文档, commit)
队列可以被清空了。这个方法会移除队列里所有未执行的函数, 但不会移除正在运行的函数。无参数的情况下调用.clearQueue()方法将会清空默认的”fx”队列。
选择符 (Selectors)
“#id p”效率更高 (commit)
所有以ID开头的选择符都得到了优化, 能够在瞬间得到返回值。所有以ID为开头的选择符速度将一直快于其他选择符。
页面遍访 (Traversing)
.index(), .index(String) (index 文档, commit)
.index() 方法经过重写, 变得更加直观和灵活。
你可以获得一个元素相对于同父元素的指数:
// 计算第一个 <li> 元素在它所有的同父元素中的指数:
$("li.current").index()
你也可以获得一个元素在一个jQuery元素集合中的指数, 这个集合可以用一个选择符或者是一个DOM元素来指定:
// 计算这个 <h3 id="more-info"> 元素在页面上所有 <h3> 元素里的指数:
$("#more-info").index("h3")
新的.has()方法 (has 文档, commit)
这个方法相当于选择符里的:has()过滤法。它拿到一个jQuery集合,返回含有指定选择符的元素。
新的 .nextUntil(), .prevUntil(), .parentsUntil() 方法 (.nextUntil() 文档, .prevUntil() 文档, .parentsUntil() 文档, commit)
新的”until”方法类似于.nextAll(), .prevAll(), 和.parents()。区别是可以用一个选择符来停止元素探索。
.add(String, Element) (.add() 文档, commit)
可以给.add()方法指定环境了。这个功能可以用于在一个调用链中加入和操作额外元素(比如Ajax请求里返回的新元素)。
.closest(filter, DOMElement) (.closest() 文档, commit)
可以通过closest方法的第2个参数设置一个DOMElement环境。给closest设置一个环境一般能够提高这个方法的运行速度。这个优 化也适用live(), 因为这个方法内部调用了closest()。
常用工具 (Utilities)
jQuery.isEmptyObject() (jQuery.isEmptyObject() 文档, commit)
如果对象,em>没有任何属性, 该方法将返回true。jQuery.isEmptyObject()方法不对参数进行任何检查, 所以请保证参数是一个对象。
jQuery.isPlainObject() (jQuery.isPlainObject(), commit )
如果一个对象是通过字符创建的(译注:{}),jQuery.isPlainObject()返回true; 如果对象是其他类别的对象(译注:如 new Object())或者是基本类型, 则返回false。
jQuery.contains() (jQuery.contains() 文档, commit)
如果两个参数都是DOM节点,并且第二个节点是嵌套在第一个节点内部的话, jQuery.contains()返回true。反之返回false。
jQuery.noop (jQuery.noop() 文档, commit)
是个空的函数, 可以用在必须要有一个函数的情况下。(译注: noop是No Operation的意思。)
jQuery.unique() (jQuery.unique() 文档)
jQuery 1.4版中, jQuery.unique()方法返回结果里的元素是按照他们在页面里的顺序排序的。由于在创建jQuery集合的时候jQuery使用 jQuery.unique()方法, 所以jQuery方法返回的集合也是按照他们在页面里的顺序排列的。
其他 (Miscellaneous)
jQuery.browser以浏览器引擎为中心 (jQuery.browser 文档, commit )
例如, 你可以通过jQuery.browser.webkit探测引擎是否是Webkit。
改进了对applets的处理 (commit 1, commit 2)
jQuery不再试图在Java applets上绑定事件或是数据了(绑定事件或是数据会出现错误)。
不再使用 arguments.callee (commit)
为了顺应Caja的 要求, 同时也因为即将开始应用的ECMAScript 5规范里将其标记为陈旧, 我们将jQuery核心中所有用到arguments.callee的代码都移除了。
用Closure Compiler替换了YUI Min (commit)
内部重组 (Internal Reorganization)
在1.4版的开 发过程中的一个重点是要建立一个更易读, 更易懂的代码库。为了达到这个目标我们树立了一系列编写代码规范的向导。
下面是一些主要的变化:
* 旧的’core.js’文件被分成了’attribute.js’, ‘css.js’, ‘data.js’, ‘manipulation.js’, ‘traversing.js’, and ‘queue.js’.
* ready事件被移入了’core.js’ (因为它是jQuery的一个基本组成之一)。
* 大部分核心代码都符合新的 代码规范 .
* css和属性的逻辑被划分开来, 不再如以往相互缠绕。
测试 (Testing)
jQuery 1.4版发布过程中我们修复了207个问题 (比较之下1.3版里有97个修复)。
jQuery 1.4.此外, 测试的数量从jQuery 1.3.2中的1504例升到了1.4中的3060例。
所有测试都在主要浏览器里完全通过了。(Safari 3.2, Safari 4, firefox 2, Firefox 3, Firefox 3.5, IE 6, IE 7,
IE 8, Opera 10.10, and Chrome)
我们尽量试图减小jQuery 1.4对大规模升级可能造成的麻烦 – 保持所有公开函数的签名不变。即使如此, 请通读下面的列表以保证你对可能对你的应用造成问题的变更。
* .add()不再简单的将 结果串联到一起, 结果将会被混合到一起, 然后根据他们在页面里的顺序排列。
* .clone(true)将 复制事件和数据, 而不仅是事件。
* jQuery.data(elem) 不再返回id, 取而代之的是元素的对象缓存。
* jQuery() (无参数) 不再自动转换成jQuery(document)了。
* 通过.val(“…”)获 得一个option或一个checkbox的值不再有歧义(将总是根据value属性选择, 而不是根据text的值)。(Commit)
* jQuery.browser.version现 在将返回引擎的版本.
* 现在起将对引入的JSON更严格, 如果JSON的格式不符将会报错。如果你需要对不符合JSON严格格式的Javascript进行估值, 你必须设置请求的文件类型为纯文本, 然后用eval()来对内容估值。
* 参数序列化默认会按照PHP/Rails的风格进行。你可以通过jQuery.ajaxSettings.traditional = true;来切换到旧的序列化方式。你也可以针对个别请求进行切换, 在调用jQuery.ajax的 时候递入{traditional: true}
* 内部的jQuery.className被移除了。
* jQuery.extend(true, …)不再扩展复杂对象或是阵列。(TODO)
* 如果一个Ajax 请求没有指定 dataType, 而返回的数据类型是”text/javascript”, 那么回复将会被执行。之前, 必须明确的指定dataType。
* 设置Ajax 请求的”ifModified” 属性会将ETags纳入考虑。
我们还针对1.4版中可能造成问题的变更编写了一个向后兼容的插件。 如果你升级到1.4以后出现问题, 可以在引入1.4版的文件之后引入这个插件。
如何使用这个插件:
<script xsrc="http://code.jquery.com/jquery.js"></script>
<script xsrc="http://code.jquery.com/jquery.compat-1.3.js"></script>
原始数据和测试页面
性能测试中我们使用了下列测试套包:
* Attributes
* Class
* DOM Manipulation
* Empty/Remove
* Function Call Profiling: 1.3.2 1.4.
英文原文: Day One- The 14 Days of jQuery
中文译文: 翻译: jQuery1.4官方文档 | coolnalu