cirry

cirry

我的原生博客地址:https://cirry.cn

在Astro中实现图片懒加载

思考#

关于图片懒加载的方法,基于Intersection Observer API实现起来很简单。

但是在 Astro 中实现起来却不同,因为这里要实现的不是网站上的图片懒加载,而是博客中图片的懒加载。

Astro 中的博客是使用 Markdown 写的,在 Frontmatter 中添加layout来指定渲染的组件,我们在打开博文的时候,组件已经加载。博文中的 image 标签都有了 src 属性,已经去发送请求获取数据了。

我一开始的想法是,在打开页面之后,图片发送请求之前,找到一个钩子函数,把 image 的 src 属性删除,存到 data-src 中。一个比window.onload更早的钩子函数,但是没有这样的方法。

所以我就想在把 markdown 渲染成 html 的时候,把 image 标签进行处理。这个思路应该是可行的,我就去翻看 Astro 的文档,还真找到了配置方法markdown.remarkPlugins

顺着官网的线索在 github 中找,我找到了这个包:remarkjs/remark,里面介绍了一段代码示例可以将 h 标签的层级缩小一级,即 h2 标签会变成 h3 标签。

import { visit } from 'unist-util-visit'

function myRemarkPluginToIncreaseHeadings() {
  return (tree) => {
    visit(tree, (node) => {
      if (node.type === 'heading') {
        node.depth++
      }
    })
  }
}

原始 md 文档:

# Hi, Saturn!

页面 html 为:

<h1>Hi, Saturn</h1>

格式化后,页面 html 为:

<h2>Hi, Saturn</h2>

从上面的示例中,我感觉到这个插件能够满足需求,于是开始动手实现。

实现#

astro.config.mjs中添加如下代码:

import { visit } from 'unist-util-visit'

function myRemarkPluginToLazyLoadImage() {
  return (tree) => {
    visit(tree, (node) => {
      if (node.type === 'image') {
        // 将url属性给alt,另外清空url,这样页面加载的时候,图片没有url属性就不会加载
        node.alt = node.url 
        node.url = ''
      }
    })
  }
}

export default defineConfig({
  ..., // 其他配置
  markdown: {
    remarkPlugins: [myRemarkPluginToLazyLoadImage],
    // 一定要加上这个,否则不会把md处理为html,而只处理插件内的代码
    extendDefaultPlugins: true, 
  }
})

在引入 md 的 astro 组件中,添加如下代码:

<script>
/* 查找到博客中的所有img标签 */
var markdownBody = document.querySelector(".markdown-body");
let images = markdownBody.querySelectorAll("img");

const callback = (entries) => {
  entries.forEach((entry) => {
    if (entry.isIntersecting) {
      const image = entry.target;
      const data_src = image.getAttribute("alt");
      image.setAttribute("src", data_src);
      observer.unobserve(image);
      }
    });
  };
/* 给每个img标签添加监听方法 */
  const observer = new IntersectionObserver(callback);
  images.forEach((image) => {
    observer.observe(image);
  });
}
</script>

到这里,我们的图片懒加载就完成啦!

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。