打造更精简的 jQuery
jQuery 已经问世超过五年了!在这段时间里,它与浏览器、网站、设备、开发者和用户一起发展。它也,嗯,增长了不少。jQuery 添加了许多有用的功能,但它也累积了一些我们不想永远支持的累赘。对于台式电脑和高速连接来说这可能不是问题,但我们希望 jQuery 也是移动设备的良好解决方案。
除了我们对更高性能的持续追求外,我们对未来版本的优先事项是缩减压缩后的文件大小。当每个新功能或错误修复也必须保留所有现有功能和行为时,要做到这一点很困难。因此,今天我们想开始一个关于通过弃用一些功能来精简 jQuery API 的讨论。以下是我们的弃用指南
- 我们认为该功能不代表使用 jQuery 的当前最佳实践。
- 该功能在实际使用中已被证明不受欢迎、令人困惑、效率低下或无效。
- 增强该功能或解决其局限性并不实用或可行。
- 在未来某个时候移除它可能会带来显著的可用性、大小或性能优势。
弃用只是您可参与的流程中的第一步。我们的目标是
- 解释弃用特定功能的原因,如上所述。
- 在弃用和移除之间提供至少一个主要版本号,通常更多。
- 为弃用功能提供替代方案,以减轻迁移带来的痛苦。
- 倾听社区对弃用和移除的反馈。
偶尔,就像 1.7 版本中的 event.layerX/layerY 一样,如果我们判断立即移除该功能比保留它更容易,我们会提前较短时间做出重大变更。这些 hopefully 将是罕见的例外。
1.7 版本的弃用
考虑到这些,我们认为以下功能自 1.7 版本开始已被弃用。使用它们的现有代码仍可正常工作,但建议的替代方案是与未来版本更好的选择。
.live() 和 .die():我们继续收到许多错误报告,并看到用户对 .live() 方法的怪癖感到困惑。常见问题现在已在其 更新的 API 页面 上有记录。我们强烈建议对新代码使用 .on() 或 .delegate(),因为它们是更好的 API。鉴于其广泛使用,我们不太可能在 1.8 版本中移除此 API,但请尽快更新您的代码。
非标准事件属性:作为我们提高事件处理程序性能的努力的一部分,我们还弃用了从原生事件对象到 jQuery 事件对象的多个事件属性的复制,并将它们在 1.8 版本中移除:attrChange、attrName、relatedNode 和 srcElement。您可以通过 event.originalEvent.NAME
访问它们,而不是通过 event.NAME
访问它们。
$.ajax() Deferred 别名:在 1.5 版本中,我们在 jqXHR 对象上定义了 .error()/,success()/.complete() 作为 Deferred 的 .fail()/.done()/.always() 方法的别名。尽管当时这似乎是个好主意,但这使得 jqXHR 成为一个非标准的 Deferred。这不好。只要有可能,请优先使用 Deferred/Promise 方法名称,而不是 jqXHR 名称。我们还需要做一些工作来提供完整的迁移路径,因此我们可能将在 1.8 版本之后继续支持这些别名。
deferred.isResolved() 和 deferred.isRejected():现在 Deferred 和 Promises 具有进度通知和方便的 .state() 方法,我们弃用了这些旧方法,并将它们在 1.8 版本中移除。使用 N-1 个布尔方法来获取 N 状态对象的 state 是一种“二十个问题”的残酷代码版本。基于 Deferred 的代码很少需要检查 state,现在返回的字符串对于调试场景来说更加方便,在这种场景中它通常被使用。
.attr(“value”) 在输入上:为了向后兼容,我们一直在这里返回当前值(如“当前在输入框中的内容”),而不是真正的属性(HTML 中的 value
属性的值)。这让我们无法提供真正的属性值,而且令人困惑,因为 W3C 选择器是基于属性而不是当前值。因此,我们弃用了此行为,并将它在 1.8 版本中移除。始终使用 .val()
方法来获取输入元素的当前实时值。在我们能够收回属性之前,您可以使用 $("selector")[0].getAttribute("value")
,除了 IE 6/7,它仍然会返回当前值。(我们的 1.8 版本解决方案将在所有浏览器上获取属性值,这也是我们渴望改变这一点的另一个原因。)
.closest(Array) 返回 Array:此签名有点奇怪,它是为旧的实时事件代码创建的,但它返回一个 Array 而不是 jQuery 对象。从 1.8 版本开始,我们计划移除它。.closest()
的其他签名仍然存在,不受影响。
.data(“events”):jQuery 将其与事件相关的 data 存储在一个名为(等等)events
的 data 对象中,该对象位于每个元素上。这是一个内部数据结构,因此在 1.8 版本中,它将从用户 data 名称空间中移除,因此它不会与相同名称的项目冲突。jQuery 的事件 data 仍然可以通过 jQuery._data(element, "events")
访问,但请注意,这是一个未记录的内部数据结构,不应修改。
$.sub() 作为插件:尽管 $.sub()
对创建插件的无干扰区域很有用,但它不供 jQuery 核心使用,也不被其他代码广泛使用,因此我们打算在 1.8 版本中将其转换为插件以节省空间。
展望 jQuery 1.8
鉴于我们对精简 jQuery 的追求,1.8 版本中新功能的筛选将非常严格。即使是与性能相关的提案也需要权衡它们使用的空间或节省的空间。可以通过插件、特殊事件、属性钩子或其他 jQuery 扩展机制实现的功能很可能会暂时留在核心之外。
这引出了一个问题,我们可以在 1.8 版本中弃用哪些东西,并最终移除它们以简化和精简库。这些东西不必完全消失;例如,它们可以移动到一个单独的插件中,并且仅在需要时才包含。看看您是如何使用 jQuery 的,并与您的同事讨论一下。
在几周内,我们将发布另一篇博客文章,向您征求有关 jQuery 1.8 的想法——所以现在就开始思考吧!
编辑:不,我们还没有移除 IE6 支持,我们也不能。正如 John Resig 在每次 jQuery 大会上提到的那样,IE6 的大多数罪过也体现在 IE7 和 IE8 上,它们加起来仍然拥有超过 三分之一 的台式机浏览器市场份额。在我们可以同时淘汰 IE7 和 IE8 之前,移除 IE6 支持没有意义。
不错的变化!
移除 IE6 支持也很好。
$.browser 可以作为插件的一个很好的候选者。无论如何,它在核心中的功能似乎并不完整。
我支持放弃 IE6 支持。我会想念 $.ajax() .error() .success() .complete(),但理解… 总体来说听起来是个好计划。
很棒的建议。我真的很想帮助你们完成这项工作。
请不要马上放弃 IE6!对于某些项目来说它仍然很重要。至少再给它一年时间!
$.fn.size() 即将寿终正寝?
我同意 Gerrit 的观点 - 请不要放弃 IE6。目前,仍然有很多用户(被迫使用它)。
jQuery 可能是唯一支持被迫为 IE6 开发的开发人员理智的东西。IMO,最好的解决方案是将 IE6 功能移到一个插件中。
请考虑像 jQuery UI 和 mootools 一样分割代码。我想将我自己的 jQuery 版本与我需要的所有部分结合起来,而不是更多。就像我可以用 Modernizr 做的那样。
作者是否会考虑为精简和方法删除发布一个 2.0 版本?主版本号更改应该表明范围更大的更改,包括“旧代码将无法工作”的更改。我只是认为那种事情在一个 1.7 -> 1.8 版本中可能会被忽略。
如果您不能在不放弃 IE7/8 支持的情况下放弃 IE6 支持,那么如何才能现在标记该功能,并为那些更关心文件大小而不是向后兼容性的人提供一个 jQuery 版本?
假设 IE 6/7/8 补丁有一天会被删除,现在对它们进行标记的任何工作都不会白费。
您可以进一步让用户在下载自定义版本之前预先选择所需的浏览器支持。选择“仅全新浏览器”选项,当速度比传统支持更重要时,可以获得最小、最快的版本。
为什么不将 jQuery 核心文件模块化,这样人们就可以像 jQuery UI 一样自定义功能?
如果我们能选择不包含 IE 6/7/8 在我们的构建中,那将是非常棒的。
我现在正在做的一个项目不支持 IE 6 或 7,另一个项目也不支持 8,所以这里可以节省大量代码。
我不知道您支持其他浏览器的历史有多久,但如果里面有针对 FF3.5 的任何内容,我宁愿排除它,我想在几个月后,一旦他们“切换”,我想移除 3.6 的任何内容。
Safari 和 Opera 的旧版本也是如此。
请构建一个选项来删除所有这些垃圾,或者至少让某人调查一下它可以节省多少代码,因为我认为它会节省很多代码。
Lea Verou 在她的博客上谈到了这个问题。我认为她称之为 jQuery“纯净”。
我们应该精简核心,而不是创建分支库。
没有任何初学者应该被迫选择使用哪个 jQuery 库。
团队应该为他做出这个决定。
我们要么完全拥抱现代浏览器,要么继续对旧浏览器感到犹豫。
大家怎么看,单独下载是一个坏主意吗?
我赞成放弃 `$.browser`。
我从来没有用过它,听说它是个不折不扣的坏家伙。
我认为现在可能是重新审视动画 API 的时候了,因为 CSS3 正在现代浏览器中流行起来。这可以很容易地放入一个插件中,供那些仍然想要跨浏览器动画的人使用,而其他人可以使用渐进增强的 CSS3 动画来代替 Javascript 驱动的动画。
感谢您没有删除 IE6 支持。
请放弃 IE6 支持。库需要抛弃 IE6。那些使用 jQuery 1.7 的人现在只需要告诉他们的老板或客户,“不,我们不能有那个功能,因为我们支持 IE6。如果你想拥有功能 X 使网站更好,我们将不得不放弃支持 IE6。)
除非我们开始给 IE6 的棺材钉钉子,准备结束我们的痛苦,否则它不会消失。
是否可以将弃用项移到一个单独的 javascript 文件中,例如 jquery.legacy.js?
能够选择每个组件会很棒.. 就像 jQueryUI 一样,不是吗?
来自法国巴黎的诚挚问候
为什么不停止对 IE 7(甚至 8)、Firefox 3.6、Opera 10.6 和 Chrome 10 及更早版本的支持?将 jQuery 分叉为传统版本和正常版本。jQuery 1.7.x 非常稳定,因此只需修复此版本中的关键错误就足够了。
版本 1.8 可以为每个现代浏览器开发。所以唯一的问题是,插件作者将支持哪个版本。但如果您已经在考虑弃用和删除函数,那么从长远来看,这将是一个问题。
版本 1.8 应该有一个 $.supported 方法来确定浏览器是否足够现代以正常工作。然后网站管理员可以显示警告或加载传统(慢速)版本。
我也在考虑 $.browser。两年前左右我就没有使用过它了,还有 jQuery.boxModel。
您还可以考虑删除 $.each、$.map、$.unique 等等,如果它们在 jQuery 核心本身中没有被大量使用。不要误会我的意思,它非常有用,但是如果你使用其他库,比如 underscore.js,你就会有双份,而且它们可以很容易地移动到一个实用程序插件中。
我梦想着拥有一个真正精简的 jQuery
./configure –no-msie –no-legacy
等等,对于其他的库也是如此。我的服务只针对真正的 HTML5 浏览器…
我完全同意 Jens 和其他关于分离 IE6-8 相关功能的意见
Jens Grochtdreis 说
———————-
请考虑像 jQuery UI 和 mootools 一样分割代码。我想将我自己的 jQuery 版本与我需要的所有部分结合起来,而不是更多。就像我可以用 Modernizr 做的那样。
我们可以创建一个投票线程,列出所有当前的 API,然后人们可以开始投票,例如最常用的 API、最不常用的 API 等。我认为这将让我们了解大家如何使用 jQuery。以及哪些功能可以弃用。
我赞成 jquery.legacy.js
一个未压缩的版本会很棒,可以添加某种警报,来跟踪(我的)代码中那些被弃用的使用方式
我真的很喜欢将 jQuery Core 模块化的想法,就像 jQuery UI 一样。这将使开发者和用户更容易支持、修复和使用。结果可以是一个非常精简、干净的核心,而所有其他一些用户可能需要(但不是大多数用户)的东西仍然可用。这意味着诸如 IE6 支持(我个人会放弃这个,但我知道 IE6 仍然被广泛使用)和 $.ajax()(我会想念这个…)。我支持这个!
对于那些要求保留 IE6 支持的人,请记住,如果 jQuery 放弃了 IE6 支持,你仍然可以坚持使用旧版本的 jQuery 来支持 IE6。对我来说这似乎是可以接受的。这并不意味着你的应用程序会因为更新的版本不支持 IE6 而神奇地停止工作。只要不要更新即可。
Andrew de Andrade 说
<>
库支持并不是 IE6 还没有消亡的原因。过早地取消库支持只会给那些需要支持那些拥有糟糕 IT 部门(感谢它们数量正在逐渐减少)的政府和企业用户以及那些针对中国用户的用户带来麻烦。这并不会促进摆脱 IE6 的进程。
还要注意,其中一个标准(非常正确)是移除会节省多少空间。我在这里看到了一些关于它会“非常大”的说法,但如果你真的看一下 jQuery 的源代码,我怀疑你会发现,虽然它很普遍(这里或那里有一两行代码),但总的来说,它实际上并没有那么*大*。并且其中很多可能仍然需要用于 IE8(它将在很长一段时间内与我们在一起)及更高版本。
不幸的是,这种普遍性也使它不适合作为插件。你基本上需要一个变体。
团队似乎正在专注于那些设计糟糕且没有被广泛使用 API,这些可能是短期收益的更好目标。
一年后,情况可能会有很大的不同。我希望如此。
(让我们再试一次,请删除上面的早期副本。[如果你要支持 HTML 标签并要求转义 <,请说明!])
Andrew de Andrade 说
库支持并不是 IE6 还没有消亡的原因。过早地取消库支持只会给那些需要支持那些拥有糟糕 IT 部门(感谢它们数量正在逐渐减少)的政府和企业用户以及那些针对中国用户的用户带来麻烦。这并不会促进摆脱 IE6 的进程。
还要注意,其中一个标准(非常正确)是移除会节省多少空间。我在这里看到了一些关于它会“非常大”的说法,但如果你真的看一下 jQuery 的源代码,我怀疑你会发现,虽然它很普遍(这里或那里有一两行代码),但总的来说,它实际上并没有那么*大*。并且其中很多可能仍然需要用于 IE8(它将在很长一段时间内与我们在一起)及更高版本。
不幸的是,这种普遍性也使它不适合作为插件。你基本上需要一个变体。
团队似乎正在专注于那些设计糟糕且没有被广泛使用 API,这些可能是短期收益的更好目标。
一年后,情况可能会有很大的不同。我希望如此。
@Paul,关于:jQuery.fn.size(),这里有一个关于它的问题:http://bugs.jquery.com/ticket/10657
明智之举。我最近一直在想 jQuery 什么时候会开始重新评估旧内容。
我想补充一点,支持将其作为 2.0 版本发布(也许可以选择组件)。这是一个相当大(潜在的)重大更改,而不是一个小更新。我可以想象,当人们看到新版本并更新而没有考虑的时候,他们会措手不及。
http://updates.html5rocks.com/2011/08/insertAdjacentHTML-Everywhere
请在 JQuery 中添加 insertAdjacentHTML 改进。
并停止支持 IE6/7,即使 Google 也不再支持这些浏览器了。
嗨,各位,
我支持移除 IE6/IE7 支持。任何需要这些功能的人应该使用旧版本,而不是升级到新版本。
添加 CSS3 动画支持,并在有意义的地方进行优雅降级,这将是对动画 API 的重大改进,正如 Scott R 所建议的那样。
我不赞成采用类似于 jQuery UI 的脚本分离方式。我认为 jQuery 当前的实现方式是完美的。它只是一个框架,而不是一个由独立实体(小部件)组成的 UI 框架,其中一些我甚至可能在我的项目中不需要。
我认为将这个版本命名为 2.0 而不是 1.8 是有道理的。上面的 Jarrett 有一点说得很好。否则,开发者可能会在编号方面迷失方向。今年已经发布了太多新的 jQuery 版本,另一个(1.8?)看起来与之前的版本没什么区别,而且不那么重大。
谢谢!
Angel
另一个支持将 jQuery 拆分为模块的投票。
我最近开始使用 Zepto,然后意识到我的几乎所有代码都可以在 Zepto 上运行,只需进行一些更改来适应 API 的细微差异。
这意味着我几乎总是只使用 jQuery 功能集的一小部分。
我无法真正切换到 Zepto,因为它不是为了支持除 WebKit 之外的任何东西而设计的,但我认为对于那些想要使用 jQuery 核心但对功能蔓延不感兴趣的人来说,存在一个空白。
许多新的 jQuery 功能与其他库提供的功能或人们自己组合的功能是重复的,而且人们很乐意使用它们。我并不是说 jQuery 不应该继续扩展,但应该将其扩展为模块,而不是作为一项要求。
如何让用户在自定义 jQuery 构建中选择他想要的哪些功能?
例如,就像 jQuery UI 一样。
我已经有一些项目,我根本不需要任何 ajax 功能,只需要 DOM 解析器和动画功能。
当您弃用 jQuery 的功能时,您会创建或更新像 jQuery.Lint 这样的工具,以允许开发者了解哪些功能将很快消失吗?
这些变化确实很有必要。祝贺 jQuery 团队。
遗憾的是,我理解保留 IE6 支持的必要性,但是从纯粹的学术角度来看,我很好奇(关于移动设备),如果删除专门支持 IE 的代码,可以减轻多少重量。
根据我的统计数据,IE 移动版的使用率微不足道……而且据我所知,Win Phone 7 支持 IE9 和相当水平的标准(假设只在标准模式下加载)。
尽管我喜欢浏览器、平台和设备的多样性,但我很高兴 IE 移动版从未成功,也没有降低移动 Web 开发的基准……
“为什么不将 jQuery 核心文件模块化,以便人们可以像 jQuery UI 一样自定义函数。”
我们需要模块化。别无选择。
D.
Stifu 说
Angel Todorov 说
这没有道理。假设一个网站由于地理原因或公司/政府原因必须支持 IE6,也许他们 20% 的访问者仍在使用它。(我负担不起放弃 20% 的用户,你会吗?再说一次,我们假设一个网站针对那些仍然使用 IE6 的政府和大型公司机构,或者针对中国,在那里它仍然超过四分之一的一般用途用户。)你说他们应该被排除在 jQuery 的错误修复、改进等之外?因为他们的用户坚持这样做而被降级为使用旧技术?那么他们(例如)80% 的用户呢?他们正在使用更新的东西吗?
不,这个等式不平衡。再说一次,没有人提供任何指标表明这样做,同时仍然支持 IE8+,会导致 jQuery 的代码大小显着减少,或者在未来显着减少工作量。
总有一天(很快)我们就能最终向这些旧浏览器说“再见”,也许在政府/公司方面的一年左右(我对中国市场的趋势一无所知)。与此同时,团队还有许多更高价值、更低风险的目标要追求。
伟大的举措!我的愿望清单
– 移除效果 (https://api.jqueryjs.cn/category/effects/)。这应该是一个插件!
– 移除所有 delegate/bind/live/click/focus/hover/dblclick 等快捷方法,这些方法可以使用 on/off 方法代替
– 移除 $.browser
– 保留 IE6 支持
我也赞成单独的模块。我并非在每个项目中都使用 Ajax 或表单。
-1 关于将 jQuery 模块化。jQuery 普及的一个原因是它能够从 CDN 获取并通过缓存包含来提高网站性能。通过将 jQuery 模块化,网站将不再受益于像 Google 这样的 CDN 中的 jQuery 以及 jQuery 版本的碎片化。我知道有很多功能是一些人不会使用的,但传播范围足够大,所以 jQuery 中的任何东西对每个人都有好处。
最好的解决方案正是他们提出的:从核心弃用并精简它,使其用途尽可能接近开发人员的需求,同时保持尽可能高效和可维护。
我认为模块化 jQuery 的想法是最好的方法。此外,将 IE 支持拆分为一个插件,将主代码保留为一个仅支持标准组件的框架。那么,要为 iOS 或 Android 等移动设备进行开发的人就可以构建一个自定义框架,从而有机会将 Web 应用程序保持得尽可能精简。
另一方面,jQuery Mobile 会利用这种情况。
说实话,我认为虽然动画曾经是 jQuery 的重要组成部分,但由于 CSS3 过渡,它们现在已经不再那么重要了,应该被分离到单独的插件中。我从不使用它们,我主要使用 jQuery 来进行查询选择器和链式操作,以及各种辅助方法(.val、.add/.remove/.hasClass),所有动画都是通过良好时间安排的类管理和现在得到广泛支持的 CSS3 过渡(以及旧浏览器的渐进增强)来完成的。
此外,我同意之前的评论者的观点,模块化。我曾经是 mootools 的用户,他们有一个很棒的页面,让你可以通过勾选框来构建自己的版本(它会自动管理依赖项),我希望 jQuery 也能做到:我可以删除动画和 IE6 支持(如果可能的话)——唯一的问题是这会给各种 CDN 和它们慷慨地托管 jQuery 版本(感谢 Google!)带来的负担以及缓存的好处。
@Eli
你可以模块化,但将“完整”副本保留在各种 CDN 上。例如,Google 仍然托管 mootools。我认为模块化最终只会产生不超过 5 个实际的“集合”来满足 90% 的需求,因此 CDN 也可以托管这些集合。
请不要删除 .live() 和 .die() – 我非常喜欢它们!当然,还有其他方法可以实现……但我一直认为它们是处理各种问题的优雅而巧妙的方式。对于任何在客户端进行大量工作的人来说,这两个方法绝对是极好的。
另一个建议……如果你想减小大小,如何尝试自己动手,比如 jQuery UI?
如果他们移除了 IE6 支持,而你仍然需要它——不用担心,你仍然可以使用当前版本。
查看代码后,我发现这些不需要
– $.browser
– .size 方法(可以直接使用 length 代替?)
– $.sub(移到插件)
– .get(我们可以直接使用 $(“#el”)[0])
– .live 和 .die(.on 和 .off API 会取代它们)
从技术上讲,jQuery 是模块化的,它只是在发布时被编译了。
如果你愿意改变发布模式,你可以从提供两个单独的 jQuery 版本开始:带有 BC 和没有 BC 的。在内部,你将弃用函数提取到一个新的源文件中,可能是 deprecated.js,在编译 jQuery 以进行部署时,你将一个包含 deprecated.js 的集合编译出来并提供给公众,并将另一个不包含的集合提供给那些开始新项目(因此没有 BC 问题)的开发人员。