jQuery Core 1.9 升级指南
- 概览
- jQuery Migrate 插件
- jQuery 1.9 中的重要变更
- .toggle( function, function, ... ) 已移除
- jQuery.browser() 已移除
- .live() 已移除
- .die() 已移除
- jQuery.sub() 已移除
- .add()
- .addBack( selector ) 取代 .andSelf()
- 针对游离节点(disconnected nodes)的 .after()、.before() 和 .replaceWith()
- .appendTo, .insertBefore, .insertAfter, 和 .replaceAll
- Ajax 事件应绑定到 document
- .trigger() 触发的 "click" 事件中的复选框/单选框状态
- 触发 "focus" 事件的顺序
- jQuery( htmlString ) 与 jQuery( selectorString )
- 不被 .data() 方法触发的事件;带有点号的名称
- jQuery 集合中游离节点的排序
- 加载并运行 HTML 内容中的脚本
- .attr() 与 .prop()
- 旧版 IE 中的 $( "input" ).attr( "type", newValue )
- "hover" 伪事件
- jQuery 对象上的 .selector 属性
- jQuery.attr()
- jQuery.ajax 返回空字符串作为 JSON 结果
- jQuery.proxy() 上下文
- .data( "events" )
- Event 对象移除的属性
- API 方法中未公开的参数
- 其他未公开的属性和方法
链接 概览
jQuery 1.9 移除或修改了几个过去表现不一致或效率低下的 API。这些更改中的大部分在之前的 jQuery 版本(特别是 1.7 和 1.8)中通过 弃用 进行了预告。
在进行这些更改时,团队的目标是修复导致 jQuery 不一致或难以使用的行为,并在此过程中优化文件大小和整体性能。
这份列表看似令人望而生畏,但大多数更改针对的是特殊情况和边界情况,还有一些是针对 jQuery 历史行为存在问题的广泛要求而进行的更改。作为第一步,查看代码是否正常工作的最佳方法是同时使用 jQuery 1.9 和下文所述的 Migrate 插件进行尝试。
目前,本指南作为标准 jQuery API 文档的附录,那些页面可能尚未描述 1.9 版本的行为。在我们更新 api.jquery.com 上的各个页面以反映 1.9 更改的过程中,请耐心等待。
链接 jQuery Migrate 插件
我们意识到现有网站和插件可能会受到这些更改的影响,因此提供了 jQuery Migrate 插件作为过渡升级路径。下文中的各个说明会指出 1.9 中更改的行为是否可以通过使用 jQuery Migrate 插件来恢复。请注意,jQuery 1.9 中的所有更改也将适用于 jQuery 2.0,且 jQuery Migrate 插件在 2.0 中同样适用。
未压缩的 jQuery Migrate 插件开发版包含控制台日志输出,可在使用特定的弃用和/或已移除功能时发出警告。这使其成为一个非常有价值的迁移调试工具,用于查找和修复现有 jQuery 代码及插件中的问题。它可以配合低至 1.6.4 版本的 jQuery 核心库进行诊断。
该插件的压缩版不会生成任何日志输出,可用于希望使用 jQuery 1.9 或更高版本、但同时必须使用旧版不兼容 jQuery 代码或插件的生产网站。理想情况下,这仅应作为短期解决方案,但具体由您决定。
更多信息请参见 jQuery Migrate 插件。
链接 jQuery 1.9 中的重要变更
下表并未列出 jQuery 1.9 的所有更改,仅列出了我们预计可能影响行为并可能破坏现有代码的更改。有关完整且详细的更改列表,请参阅 jQuery 博客 上的发布公告中的更新日志,或访问 bugs.jquery.com。
链接 .toggle( function, function, ... ) 已移除
这是 .toggle() 的“点击元素以运行指定函数”的签名。不应将其与 .toggle() 的“更改元素的可见性”混淆,后者并未弃用。前者被移除是为了减少混淆并提高库的模块化潜力。jQuery Migrate 插件可用于恢复此功能。
链接 jQuery.browser() 已移除
jQuery.browser() 方法自 jQuery 1.3 起已被弃用,并在 1.9 中移除。如果需要,可以通过 jQuery Migrate 插件使用。我们建议使用 Modernizr 等库进行功能检测。
链接 .live() 已移除
.live() 方法自 jQuery 1.7 起已被弃用,并在 1.9 中移除。我们建议升级代码以改用 .on() 方法。例如,为了精确匹配 $( "a.foo" ).live( "click", fn ),你可以改写为 $( document ).on( "click", "a.foo", fn )。更多信息请参见 .on() 文档。在此期间,可以使用 jQuery Migrate 插件来恢复 .live() 功能。
链接 .die() 已移除
.die() 方法自 jQuery 1.7 起已被弃用,并在 1.9 中移除。我们建议升级代码以改用 .off() 方法。例如,为了精确匹配 $( "a.foo" ).die( "click" ),你可以改写为 $( document ).off( "click", "a.foo" )。更多信息请参见 .off() 文档。在此期间,可以使用 jQuery Migrate 插件来恢复 .die() 功能。
链接 jQuery.sub() 已移除
jQuery.sub() 方法已移动到 jQuery Migrate 插件中。证明其有价值的使用场景数量不足以支持将其保留在核心库中。jQuery Migrate 插件重新添加了此功能。
链接 .add()
.add() 方法理应始终按文档顺序返回结果。在 1.9 之前,如果上下文或输入集合以游离节点(不在文档中)开头,.add() 不会按文档顺序对节点排序。现在,节点始终按文档顺序返回,而游离节点被置于集合末尾。
链接 .addBack( selector ) 取代 .andSelf()
从 jQuery 1.8 开始,.andSelf() 方法已被弃用,取而代之的是 .addBack() 方法,我们认为后者更能体现该方法的功能——“加回(add back)”前一个结果集。新方法接受一个可选的选择器,可用于在将前一个集合添加到当前集合之前对其进行过滤。例如,$( "section, aside" ).children( "ul" ).addBack( "aside" ) 的结果集将包含所有 aside 节点以及 section 和 aside 节点的 ul 子元素,按文档顺序排列。虽然 .andSelf() 在 1.9 中仍然有效,但我们建议尽快更改名称。jQuery Migrate 插件会对 .andSelf() 的使用发出警告。
链接 针对游离节点的 .after()、.before() 和 .replaceWith()
在 1.9 之前,如果集合中的第一个节点未连接到文档,.after()、.before() 和 .replaceWith() 会尝试在当前 jQuery 集合中添加或更改节点,并在这些情况下返回一个新的 jQuery 集合,而不是原始集合。这导致了若干不一致和明显的错误——该方法可能会也可能不会根据其参数返回新结果!从 1.9 开始,这些方法始终返回原始的、未修改的集合,并且尝试在没有父节点的节点上使用 .after()、.before() 或 .replaceWith() 将不起作用——也就是说,集合及其包含的节点都不会被更改。
链接 .appendTo, .insertBefore, .insertAfter, 和 .replaceAll
从 1.9 开始,这些方法始终返回一个新集合,使其能够一致地用于链式调用和 .end() 方法。在 1.9 之前,仅当存在单个目标元素时,它们才会返回旧集合。请注意,这些方法始终返回追加到目标元素的所有元素的聚合集合。如果没有元素被目标选择器选中(例如,$( elements ).appendTo( "#not_found" )),结果集将为空。
链接 Ajax 事件应绑定到 document
从 jQuery 1.9 开始,全局 Ajax 事件(ajaxStart, ajaxStop, ajaxSend, ajaxComplete, ajaxError, 和 ajaxSuccess)仅在 document 元素上触发。请更改程序以在 document 上监听 Ajax 事件。例如,如果代码当前如下所示:
|
1
2
3
|
|
请将其更改为:
|
1
2
3
|
|
链接 .trigger() 触发的 "click" 事件中的复选框/单选框状态
当用户点击复选框或单选按钮时,事件处理程序看到的节点处于其在 event.preventDefault() 未被调用时的状态——本质上是其新状态。例如,如果用户点击一个未选中的复选框,事件处理程序将看到一个已选中的框。在 1.9 之前,由 .trigger( "click" ) 或 .click() 触发的合成事件看到的复选框状态与用户操作的状态相反。这在 1.9 中已修复,以反映与用户启动操作相同的选中状态。
链接 触发 "focus" 事件的顺序
当用户点击或通过 Tab 键切换到表单元素以使其获得焦点时,浏览器首先为之前获得焦点的元素触发 blur 事件,然后为新元素触发 focus 事件。在 1.9 之前,使用 .trigger( "focus" ) 或 .focus() 触发的 focus 事件会先为新元素触发 focus 事件,然后为之前的元素触发 blur 事件,最后才真正使元素获得焦点。在 1.9 中,此行为已更改,以反映与用户引起焦点更改时相同的顺序。
对于原生 DOM focus 事件,只有当目标元素尚未获得焦点且可以成功获得焦点时,浏览器才会调用 focus 事件处理程序。jQuery 始终确保调用 .trigger( "focus" ) 或 .focus() 会一致地运行任何附加的事件处理程序,即使元素无法获得焦点,jQuery 1.9 仍保持这一做法。这与 DOM .focus() 方法的行为不同,后者在许多情况下(包括元素已获得焦点或元素被禁用时)不会调用事件处理程序。
不幸的是,所有版本的 Internet Explorer(6 到 10)都会异步触发 focus 事件。当你在 IE 中 .trigger( "focus" ) 时,jQuery 不会“看到”稍后发生的异步 focus 事件,因此它会自行触发一个 focus 事件,以确保始终如上所述发生焦点事件。这会导致事件处理程序被调用两次。要避免这种重复调用(但风险是事件处理程序可能根本不被调用),请直接使用 DOM focus 方法,例如 $( "selector" ).get( 0 ).focus()。
链接 jQuery( htmlString ) 与 jQuery( selectorString )
在 1.9 之前,如果字符串中任何位置包含 HTML 标签,该字符串就会被视为 HTML 字符串。这有可能导致代码的意外执行并拒绝有效的选择器字符串。从 1.9 开始,字符串只有在以小于号("<")字符开头时才被视为 HTML。Migrate 插件可用于恢复 1.9 之前的行为。
如果已知字符串是 HTML,但可能以非 HTML 标签的任意文本开头,请将其传递给 jQuery.parseHTML(),它将返回一个代表标记的 DOM 节点数组。可以从中创建 jQuery 集合,例如:$( $.parseHTML( htmlString ) )。例如在处理 HTML 模板时,这被视为最佳实践。对于字面量字符串的简单使用,如 $( "<p>Testing</p>" ).appendTo( "body" ),不受此更改影响。
底线:传递给 jQuery() 的、以小于号以外字符开头的 HTML 字符串将被解释为选择器。由于字符串通常无法被解释为选择器,最可能的结果是由 Sizzle 选择器引擎抛出“无效的选择器语法”错误。使用 jQuery.parseHTML() 来解析任意 HTML。
使用 jQuery Migrate 插件时,它将使用旧规则来确定传递给 $() 的字符串是否“看起来像 HTML”。
链接 不被 .data() 方法触发的事件;带有点号的名称
.data() 方法曾有一种未公开且性能极低的方式来监控值的设置和获取,该方式在 1.9 中已被移除。这以一种积极的方式影响了对包含点号的数据名称的解释。从 1.9 开始,调用 .data( "abc.def" ) 仅检索名为 "abc.def" 的数据,而绝不只是 "abc"。请注意,更底层的 jQuery.data() 方法从未支持过事件,因此没有改变。jQuery Migrate 插件不会为此案例恢复旧行为。
链接 jQuery 集合中游离节点的排序
在许多版本中,几乎所有返回新节点集的 jQuery 方法都使用文档顺序对结果集进行排序。(有少数方法如 .parents() 会按文档反序返回结果,但这些例外情况已有文档说明,且在 1.9 中未发生变化。)
在 1.9 之前,包含部分连接节点和部分游离节点的集合排序不一致,这取决于游离节点是否排在原始未排序集合的前面。从 1.9 开始,连接节点始终按文档顺序放在集合开头,游离节点放在其后。jQuery Migrate 插件不会恢复这种有些随机且不可预测的旧行为。
链接 加载并运行 HTML 内容中的脚本
在 1.9 之前,任何接受 HTML 的方法(例如 $()、.append() 或 .wrap())都会执行 HTML 中的任何脚本,并将其从文档中移除以防止再次执行。但在某些情况下(如脚本可能被移除并使用 .wrap() 等方法重新插入文档时),这仍会出问题。从 1.9 开始,插入到文档中的脚本会被执行,但会留在文档中并被标记为已执行,因此即使被移除并重新插入,它们也不会再次执行。
尽管有此更改,但在 HTML 标记中混入可执行 JavaScript 是非常糟糕的做法;它会涉及设计、安全、可靠性和性能方面的问题。例如,HTML 中包含的外部脚本标签是同步获取并执行的,这可能耗费大量时间。目前没有接口可以在这些脚本加载完成或加载失败时发送通知,也无法在发生错误时采取补救措施。
尝试通过克隆现有脚本标签并将其注入文档来加载脚本的代码将不再起作用,因为克隆的脚本标签已被标记为已执行。要加载新脚本,请改用 jQuery.getScript()。
链接 .attr() 与 .prop()
jQuery 1.6 引入了 .prop() 方法用于设置或获取节点上的属性(properties),并弃用了使用 .attr() 设置属性的做法。然而,直到 1.9 之前的版本仍在特定情况下继续支持使用 .attr()。为了向后兼容而保留的这种行为,在区分 attribute 和 property 的选择器被使用时会引起混淆。
例如,复选框上的布尔 attribute(如 checked 和 disabled)会受此更改影响。"input[checked]" 的正确行为是选择具有 checked attribute 的复选框,无论其字符串值为何,也无论其当前状态如何。相比之下,"input:checked" 选择的是当前被选中的复选框,这反映在其布尔值(true 或 false)的 checked property 中,该 property 会在用户点击选框等情况下发生变化。1.9 之前的版本有时无法通过这些选择器选中正确的节点。
以下是在复选框上设置 checked 的正确用法示例;同样的规则适用于 disabled。请注意,只有 property 能在所有浏览器中一致地反映和更新复选框的当前状态;你极少需要去设置 attribute。
|
1
2
3
4
5
6
7
8
9
|
|
input 元素上的 value property 与 attribute 是这种模糊性的另一个例子。attribute 通常反映从 HTML 标记中读取的值;property 反映当前值。由于 .val() 方法是推荐的 jQuery 获取或设置表单元素值的方式,这种混淆通常不会影响用户。
然而,当使用像 "input[value=abc]" 这样的选择器时,它应该始终通过 value attribute 进行选择,而不应受用户对 property 所做的任何更改(例如用户在文本输入框中输入内容)的影响。从 jQuery 1.9 开始,此行为已正确且一致。早期版本的 jQuery 有时会在本应使用 attribute 时使用了 property。
jQuery Migrate 插件会恢复旧的 attribute 与 property 规则。
链接 旧版 IE 中的 $( "input" ).attr( "type", newValue )
在 1.9 版本之前,jQuery 会在所有浏览器中对任何尝试设置 input 或 button 元素 type attribute 的行为抛出异常。这样做是为了兼容最低标准;IE 6/7/8 在你尝试更改 input 元素类型时会报错。从 jQuery 1.9 开始,如果浏览器允许,我们允许你设置元素的类型。但是,你自己的代码需要意识到在旧版 IE 上执行此操作仍会报错。jQuery Migrate 插件会在你尝试设置 type attribute 时发出警告,但不会抛出 JavaScript 错误。
链接 "hover" 伪事件
从 1.9 开始,不再支持将事件名称字符串 "hover" 作为 "mouseenter mouseleave" 的同义词。这允许应用程序附加并触发自定义的 "hover" 事件。更改现有代码只需简单的查找/替换,且 jQuery Migrate 插件也支持 "hover" 伪事件以简化迁移。
链接 jQuery 对象上的 .selector 属性
已弃用的 jQuery 对象 .selector 属性仅存的目的是为了支持已弃用的 .live() 事件。在 1.9 中,jQuery 不再尝试在链式方法中维护此属性,因为链式方法的使用从未被 .live() 支持过。请不要使用 jQuery 对象上的 .selector 属性。jQuery Migrate 插件也不尝试维护此属性。
链接 jQuery.attr()
在 1.9 中,我们移除了使用 pass 参数的未公开签名 jQuery.attr( elem, name, value, pass )。任何依赖此签名的代码都应重写,但 jQuery Migrate 插件可以提供向后兼容的行为,并会在使用此签名时发出警告。
链接 jQuery.ajax 返回空字符串作为 JSON 结果
在 1.9 之前,预期返回数据类型为 JSON 或 JSONP 的 ajax 调用会将返回空字符串视为成功情况,但会向成功处理程序或 promise 返回 null。从 1.9 开始,为 JSON 数据返回的空字符串被视为畸形的 JSON(因为它确实是);这现在将抛出错误。请使用错误处理程序来捕获此类情况。
链接 jQuery.proxy() 上下文
1.9 中的新变化:通过调用带有假值(falsy)上下文的 jQuery.proxy 返回的函数,将为所提供的函数保留其 this 对象。以前,上下文的假值如果是 null/undefined,会被转换为全局对象 (window),否则会被包装在对象中(例如 new Boolean( false ))。
链接 .data( "events" )
在 1.9 之前,如果没有其他代码定义过名为 "events" 的数据元素,.data( "events" ) 可用于检索元素的 jQuery 未公开内部事件数据结构。这一特殊情况在 1.9 中已被移除。目前没有公共接口可以检索此内部数据结构,且它仍处于未公开状态。但是,jQuery Migrate 插件为依赖此行为的代码恢复了该功能。
链接 Event 对象移除的属性
Event 对象的 attrChange、attrName、relatedNode 和 srcElement 属性在 jQuery 1.7 中就已弃用,因为它们是非标准的且不具备跨浏览器兼容性;从 jQuery 1.9 开始,它们不再被复制到传递给事件处理程序的 Event 对象中。在任何版本的 jQuery 上,仍然可以在支持这些属性的浏览器上通过使用 event.originalEvent 而不是 event 来访问它们。jQuery Migrate 插件也会将这些属性重新添加回 Event 对象。
链接 API 方法中未公开的参数
在 1.9 之前,有几个 API 方法拥有改变其行为的未公开参数,这造成了意外误用或不正确 hack(duck punching)的潜在风险。这些参数现已被移除。受影响的方法包括 jQuery.data()、jQuery.removeData() 和 jQuery.attr()。jQuery Migrate 插件不支持这些未公开参数,因为重构后的代码不再需要它们。
链接 其他未公开的属性和方法
以下内部属性和方法从未公开过,并在 1.9 中被移除。任何依赖于它们的代码都应重写。
jQuery.deletedIdsjQuery.uuidjQuery.attrFnjQuery.clean()jQuery.event.handle()jQuery.offset.bodyOffset()