当前位置: 首页 > 科技观察

一种减少JavaScript代码量的方法

时间:2023-03-12 19:53:13 科技观察

如今,越来越多的网站依赖JavaScript来提供交互。虽然JavaScript可以提供愉快的体验,但它也有一些缺点:页面加载时间更长;在加载并纠正JavaScript之前,无法使用页面;团队需要足够的手段和资源来专注于可用性、响应性和可访问性。鉴于这些缺点,我们可以依赖浏览器提供的原生解决方案,这不仅可以降低成本,还可以享受社区创建的Web标准专业知识的优势。通常,这些解决方案的代码密集度较低,因此它们还减少了开发团队的维护工作(例如,无需更新使用的库)。在本文中,让我们探讨一些可供大多数用户使用的本机解决方案。我会举一些例子,但不会详述所有细节。渲染被JavaScript阻塞在介绍各种技巧之前,首先需要提醒大家使用JavaScript的一大缺点:浏览器只有一个线程来控制页面的渲染。运行JavaScript时,浏览器会延迟用户交互事件和界面更新。这很烦人,因为你会觉得页面没有响应你的操作,或者动画会感觉卡住了。谷歌工程师PhilipWalton详细阐述了这个优化,如果你有兴趣,可以看看:https://calendar.perfplanet.com/2020/html-and-css-techniques-to-reduce-your-javascript/Developmentteam日常工作偏爱功能强大的设备,因此JavaScript的负面影响可能会被掩盖。但不要忘记对功能有限的设备进行定期测试。限制显示的行数JavaScript版本以下是在JavaScript中执行此操作的两种方法:限制显示的字符数。这种方法很容易出错,因为除等宽字体外,字体通常具有可变宽度。结果,最终显示的文本通常比预期的要长,或者中途被截断。试验元素显示的内容,直到达到理想的行数。这是昂贵的,因为每次尝试都需要浏览器在看到显示的内容之前完成渲染。并且这种技术只能在使用指定字体渲染后才能得到准确的结果,这可能会导致较大的布局偏移。当页面包含大量需要截断的文本时,页面显示会延迟。此外,这两种解决方案都会完全截断文本,可能会影响搜索引擎或辅助技术的恢复。页面上元素的字体大小或宽度也可能发生变化。考虑所有情况很麻烦。Native-webkit-line-clamp是原生CSS属性。十年前在Safari中引入,今天被广泛使用,其他浏览器出于兼容性原因采用它,并且它是一个标准。您需要一些其他前缀属性来实现所需的行为。虽然使用带前缀的属性有点烦人,但前缀在标准中有详细记录,所以这样做没有风险。除了IE和Firefox68之前的版本,所有浏览器都支持该属性,下面举例说明具体用法。HTML:Spilllitterbox,scratchatowner,destroyallfurniture,especiallycouch

Clawsintheeyeofthebeholder
Relentlesslypursuesmotheattoomuchthenproceedtoregurgitatealloverlivingroomcarpetwhilehumanseatdinner
CSS:/*Bydefault,truncatethetextabruptly*/.line-clamp{/*小心计算最大高度,itneedstomatchn*line-height*/max-height:calc(2*1.15*1.5rem);overflow:hidden;}/*Forcapablebrowsers,truncatewithanellipsis*//*要模拟没有支持的浏览器,你可以在下面的行中添加asafterclamp*/@supports(-webkit-line-clamp:2){.line-clamp{/*去掉madeupmax-height*/max-height:none;/*这三个属性是必须的,soisoverflow:hiddentthatwedefinedearlier*/display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;}}/*Extracodeforthelookofthedemo*/.demo-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(13rem,1fr));gap:1rem;margin:1rem;}.demo-card{background-color:#E2E8F0;border-radius:0.5rem;display:flex;flex-direction:column;padding:0.5rem;}.demo-img{align-self:center;margin-bottom:0.5rem;边界半径:0.5rem;}.demo-title{font-size:1.5rem;margin:0;}此解决方案没有性能或页面内容偏移问题,也不会影响搜索引擎或辅助技术。但是,它不适用于具有多个子元素的元素。重要元素始终出现在页面上有时,您希望页面的某个部分始终显示在视图中,例如页眉、工具栏或购物车。我遇到过很多这种行为,但很少有人能够做到正确。JavaScript版本如果要通过JavaScript实现此功能,则必须监听频繁触发的滚动事件。大多数解决方案通常通过限流或去抖动技术来消除大多数事件。现在,我们可以使用IntersectionObserver仅在元素进入或离开窗口时接收事件。这样做效率更高。当检测到元素进入或离开窗口时,我们需要从position:relative切换到position:fixed。这需要浏览器重新计算大量元素的大小和位置(我们称之为页面重新布局),代价高昂。我们需要确保周围的元素不会四处移动,也不会导致内容跳动。如果在元素进入或退出窗口时渲染被阻塞(如果动画与滚动协调,则很可能发生这种情况),那么切换将进一步延迟。本机CSS具有启用此行为的属性position:sticky,并且不存在性能、响应能力或内容跳跃问题:只要浏览器可以滚动,它就会将元素准确定位在您声明它的位置。您可以使用top、bottom、left或right来选择定位。除了IE和旧版本的Chrome或Firefox之外,所有浏览器都支持htmlCSSsticky。对于这些较旧的浏览器,该元素仅支持默认值position:static并且不处理top、bottom、left和right值。如果您需要支持这些浏览器,请记住这一点。旧版本的Safari需要-webkit-sticky前缀。但是这个属性有一个局限性:不能根据元素是否粘性来改变元素的外观,比如使用伪类如:stuck。这是CSS的一个常见限制。在这种情况下,我推荐使用position:sticky来设置粘性属性,结合IntersectionObserver来改变它的外观(注意不要改变大小以防止内容跳动)。平滑滚动的JavaScript版本要在JavaScript中实现这一点,您需要定期执行更改滚动位置的JavaScript。为了让动画流畅运行,整个动画运行过程中不能有其他JavaScript阻塞渲染。此外,您需要选择计时功能。为了看起来自然,可能需要为每个操作系统使用不同的计时功能,以符合该操作系统的一般做法。原生CSS有一个属性scroll-behavior:smooth和{behavior:'smooth'}可以替代JavaScript的scroll、scrollTo和scrollIntoView,将所有时间决定权留给CSS。这可能更符合常用设备的惯例。Safari尚不支持此功能(除非启用了隐藏选项),但大多数时候,这没什么大不了的。无论你使用htmlCSSJavaScript还是原生,有两个可访问性问题你需要注意:遵循设置最小化动画和页面移动,并确保焦点正确移动。滚动到捕捉点这样,您可以创建幻灯片、水平列表、捕捉到每个图像或部分,以便它们占据整个窗口。JavaScript版本要创建幻灯片,我们需要监听:鼠标点击事件(mousedown、mouseup、touchstart、touchend、pointerdown或pointerup);移动事件(mousemove、touchmove或pointermove)。正确处理所有指针事件(鼠标或触摸)和处理鼠标指针离开区域的事件非常棘手。如果你正确地处理这些事件,你可以相应地移动元素。每一步都可能导致代价高昂的重新布局,从而破坏显示效果。如果每个section占据了整个窗口或者遇到了一个水平列表,我们必须监听所有的scroll事件并替换成我们需要的scroll处理。获得预期的效果非常困难,因为我们需要完全控制本机滚动行为。无论哪种情况,您都需要使用原始页面移动速度和距离来确定是否应该移动到下一个项目。如果您的选择不符合系统的行为,可能会给用户带来困惑。本机CSS滚动捕捉处理此行为。在滚动容器中,定义一个scroll-snap-type来指示捕捉的方向,以及是否必须发生捕捉或仅在接近捕捉点时发生捕捉。然后在容器的子元素中定义scroll-snap-align来表示对齐点。下面的演示根本不使用JavaScript。它还使用滚动行为来提示用户使用正常的滚动机制。选中此框以使用IntersectionObserver在缩略图中突出显示当前图像。所有现代浏览器都支持htmlCSSJS行为。还有另一种语法(https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Scroll_Snap/Browser_compat),但我不推荐它。它只是增加了测试的负担,你可以依靠优雅的降级来解决那个问题。在不支持滚动捕捉的浏览器中,此功能将降级为正常滚动。不管是鼠标的情况还是触摸屏的情况,由于使用了浏览器的滚动功能,这种方式要比JavaScript方式流畅很多。JavaScript的延迟图像加载要在JavaScript中执行此操作,请使用类似的语法。当图像靠近视口时,使用Javascript更改图像的属性来加载和显示图像。这种方法的主要缺点是在执行相应的JavaScript之前不会显示图像。而且它发生的频率比你想象的要高。搜索引擎也很难看到图像,因为它们基本上不存在,爬虫也不会滚动屏幕。选择何时触发加载非常重要。如何根据当前带宽以及距离视口多远来决定何时加载图像?是否应该考虑滚动的速度?原生去年,所有浏览器(Safari除外)都在元素上实现了loading="lazy"属性。如果您的站点加载所有图像,请尝试使用此属性。让您的网站加载速度更快,几乎无需任何费用。如果您已经在使用某种延迟加载技术,那么在Safari支持此属性之前,您需要自己做出决定。放弃Safari的延迟加载来换取更简单的代码是否值得?目前,触发下载的规则由各个浏览器决定,可能不是最佳时机。但有一点是可以肯定的,浏览器的决定会越来越理想,无需改动任何代码!总之,我希望本文能给您一些启发,让您在下次寻找JavaScript库来做某事时考虑这些技术。此外,您还可以查看我未提及的其他HTML或CSS技术(例如
)。浏览器在不断进化,给用户带来惊喜和福利!