懒惰的图像在Svelte中
网站速度优化技巧之一:仅在需要时(即图像进入视口时)下载图像,这就是“懒加载”。此技术已存在一段时间,并且有很多关于如何实现它的优秀教程。
然而,即使资源充足,懒加载的实现方式也会因项目或框架而异。本文将结合使用Intersection Observer API和onLoad事件,利用Svelte JavaScript框架实现图像懒加载。
如果您不熟悉Svelte框架,可以参考Tristram Tolliday的Svelte入门介绍。
实战示例
我在测试Shop Ireland(一个基于Svelte和Sapper的应用程序)的速度时,整合了这种方法。我们的目标是使其尽可能快。首页的性能受到影响,因为浏览器下载了许多屏幕上根本没有显示的图像,因此我们自然而然地转向懒加载。
Svelte本身已经非常快,因为所有代码都是预编译的。但是,一旦我们为图像添加了懒加载,速度得到了显着提升。
我们将一起完成这个过程。您可以从GitHub获取此演示的最终代码,并阅读其工作原理说明。
最终效果如下:
快速启动Svelte
您可能已经有了一个Svelte应用程序,但如果没有,让我们创建一个新的Svelte项目并在本地运行它。在命令行中输入:
npx degit sveltejs/template my-svelte-project cd my-svelte-project npm install npm run dev
现在,您应该可以在http://localhost:5000上运行一个入门应用程序。
添加components文件夹
初始的Svelte演示只有一个App.svelte文件,还没有组件。让我们设置此演示所需的组件。由于没有components文件夹,所以在src文件夹中创建一个。在这个文件夹中,创建一个Image文件夹——它将保存我们此演示的组件。
我们将让我们的组件做两件事。首先,它们将检查图像何时进入视口。然后,当图像进入时,组件将在显示图像之前等待图像文件加载完成。
第一个组件将是一个<intersectionobserver></intersectionobserver>
,它围绕第二个组件<imageloader></imageloader>
进行包装。我喜欢这种设置的原因是,它允许每个组件专注于执行一项操作,而不是尝试在一个组件中打包一堆操作。
让我们从<intersectionobserver></intersectionobserver>
组件开始。
观察交叉点
我们的第一个组件将是Intersection Observer API的一个工作实现。 Intersection Observer是一个相当复杂的东西,但其要点是它监视子元素,并在子元素进入其父元素的边界框时通知我们。因此,图像可以作为某些父元素的子元素,当它们滚动到视图中时,我们可以提前得到提示。
虽然深入了解Intersection Observer API的来龙去脉是一个好主意——Travis Almand对此有一个很好的描述——但我们将使用Rich Harris为svelte.dev编写的方便的Svelte组件。
在深入了解它的具体功能之前,我们先设置它。创建一个新的IntersectionObserver.svelte文件,并将其放入src/components/Image文件夹中。我们将在这里使用以下代码定义组件:
import { onMount } from 'svelte'; export let once = false; export let top = 0; export let bottom = 0; export let left = 0; export let right = 0; let intersecting = false; let container; onMount(() => { if (typeof IntersectionObserver !== 'undefined') { const rootMargin = `${bottom}px ${left}px ${top}px ${right}px`; const observer = new IntersectionObserver(entries => { intersecting = entries[0].isIntersecting; if (intersecting && once) { observer.unobserve(container); } }, { rootMargin }); observer.observe(container); return () => observer.unobserve(container); } // Older browser fallback function handler() { const bcr = container.getBoundingClientRect(); intersecting = ( (bcr.bottom bottom) > 0 && (bcr.right right) > 0 && (bcr.top - top) window.removeEventListener('scroll', handler); }); div { width: 100%; height: 100%; } <div bind:this="{container}"> <slot></slot> </div>
我们可以将此组件用作其他组件的包装器,它将为我们确定包装的组件是否与视口相交。
如果您熟悉Svelte组件的结构,您会看到它遵循一个模式,该模式从脚本开始,进入样式,然后以标记结束。它设置了一些我们可以传递的选项,包括once属性,以及屏幕边缘的顶部、右侧、底部和左侧距离的数值,这些数值定义了交叉点开始的位置。
我们将忽略距离,而是使用once属性。这将确保图像只加载一次,因为它们进入了视口。
组件的主要逻辑位于onMount部分。这将设置我们的观察者,用于检查我们的元素以确定它是否与屏幕的可见区域“相交”。
对于旧版浏览器,它还会附加一个滚动事件来检查我们滚动时元素是否可见,然后如果我们确定它可用且once为true,它将删除此侦听器。
加载图像
让我们使用<intersectionobserver></intersectionobserver>
组件通过将其包装在<imageloader></imageloader>
组件周围来有条件地加载图像。同样,这是从<intersectionoberserver></intersectionoberserver>
接收通知的组件,因此它知道该加载图像了。
这意味着我们需要在components/Image中创建一个新的组件文件。让我们将其命名为ImageLoader.svelte。以下是我们想要在其内使用的代码:
export let src export let alt import IntersectionObserver from './IntersectionObserver.svelte' import Image from './Image.svelte' <intersectionobserver let:intersecting="{intersecting}" once="{true}"> {#if intersecting} <image src="%7Bsrc%7D" alt="{alt}"></image> {/if} </intersectionobserver>
此组件采用一些与图像相关的属性——src和alt——我们将使用它们来创建图像的实际标记。请注意,我们在脚本部分导入了两个组件,包括我们刚刚创建的<intersectionobserver></intersectionobserver>
和另一个名为<image></image>
的组件,我们还没有创建它,但稍后会介绍。
<intersectionobserver></intersectionobserver>
通过充当即将创建的<image></image>
组件的包装器来发挥作用。查看其属性。我们将once设置为true,因此图像只在我们第一次看到它时加载。
然后我们使用Svelte的slot属性。它们是什么?我们接下来介绍。
使用slot属性传递值
像我们的<intersectionobserver></intersectionobserver>
这样的包装组件对于将属性传递给它包含的子组件非常方便。 Svelte为我们提供了名为slot属性的东西来实现这一点。
在我们的<intersectionobserver></intersectionobserver>
组件中,您可能注意到了这一行:
<slot></slot>
这将intersecting属性传递给任何我们给它的组件。在这种情况下,我们的<imageloader></imageloader>
组件在使用包装器时接收该属性。我们使用let:intersecting={intersecting}访问该属性,如下所示:
<intersectionobserver let:intersecting="{intersecting}" once="{true}"></intersectionobserver>
然后,我们可以使用intersecting值来确定何时加载<image></image>
组件。在这种情况下,我们使用if条件来检查何时是加载时机:
<intersectionobserver let:intersecting="{intersecting}" once="{true}"> {#if intersecting} <image src="%7Bsrc%7D" alt="{alt}"></image> {/if} </intersectionobserver>
如果发生交叉,则加载<image></image>
并接收alt和src属性。您可以在此Svelte教程中了解更多关于slot属性的信息。
我们现在已经准备好代码,以便在图像滚动到屏幕上时显示<image></image>
组件。让我们最终开始构建该组件。
在加载时显示图像
是的,您猜对了:让我们向components/Image文件夹添加一个Image.svelte文件,用于我们的<image></image>
组件。这是接收我们的alt和src属性并在img元素上设置它们的组件。
以下是组件代码:
export let src export let alt import { onMount } from 'svelte' let loaded = false let thisImage onMount(() => { thisImage.onload = () => { loaded = true } }) img { height: 200px; opacity: 0; transition: opacity 1200ms ease-out; } img.loaded { opacity: 1; } <img src="/static/imghw/default1.png" data-src="https://img.php.cn/" class="lazy" alt="Lazy Loading Images in Svelte">
再次查看演示:
请记住,您可以从GitHub下载此演示的完整代码。如果您想在一个生产网站上看到它的运行效果,请查看我的Shop Ireland项目。懒加载用于首页、类别页面和搜索页面,以帮助提高速度。我希望您能将其用于您自己的Svelte项目!
以上是懒惰的图像在Svelte中的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

您是否曾经在项目上需要一个倒计时计时器?对于这样的东西,可以自然访问插件,但实际上更多

格子呢是一块图案布,通常与苏格兰有关,尤其是他们时尚的苏格兰语。在Tartanify.com上,我们收集了5,000多个格子呢
