懒加载和预加载和楼层式加载

懒加载的实现方式

懒加载的实现主要通过监听用户行为(如滚动触发事件)来判断何时加载内容。常见的实现方法有:

1. 使用 IntersectionObserver 实现懒加载(现代浏览器)

IntersectionObserver 是一个现代浏览器的 API,用于异步检测目标元素是否进入视口(viewport)。这是最推荐的懒加载实现方式,因为它高效且无需频繁监听滚动事件。

示例:图片懒加载

HTML:

ini 复制代码
html
复制代码
<img class="lazy" data-src="image1.jpg" alt="Lazy image 1" />
<img class="lazy" data-src="image2.jpg" alt="Lazy image 2" />
<img class="lazy" data-src="image3.jpg" alt="Lazy image 3" />

CSS:

css 复制代码
css
复制代码
.lazy {
  opacity: 0;
  transition: opacity 0.5s;
}
.lazy.loaded {
  opacity: 1;
}

JavaScript:

javascript 复制代码
javascript
复制代码
document.addEventListener("DOMContentLoaded", function() {
  const lazyImages = document.querySelectorAll('.lazy'); // 选择所有懒加载的图片

  if ('IntersectionObserver' in window) {
    const imageObserver = new IntersectionObserver((entries, observer) => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          const img = entry.target;
          img.src = img.dataset.src; // 加载图片
          img.classList.add('loaded'); // 图片加载完后显示
          observer.unobserve(img); // 停止观察已加载的图片
        }
      });
    });

    lazyImages.forEach(image => {
      imageObserver.observe(image); // 对每个图片进行观察
    });
  } else {
    // 如果不支持 IntersectionObserver, 退回到滚动事件监听方案
    console.log("IntersectionObserver not supported.");
  }
});
2. 使用 scroll 事件实现懒加载(旧浏览器)

对于不支持 IntersectionObserver 的旧浏览器(如 IE),可以通过监听 scroll 事件并手动检测元素是否进入视口来实现懒加载。

示例:图片懒加载

JavaScript:

javascript 复制代码
javascript
复制代码
function isElementInViewport(el) {
  const rect = el.getBoundingClientRect();
  return (
    rect.top >= 0 &&
    rect.left >= 0 &&
    rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
    rect.right <= (window.innerWidth || document.documentElement.clientWidth)
  );
}

function lazyLoad() {
  const lazyImages = document.querySelectorAll('.lazy');
  lazyImages.forEach(img => {
    if (isElementInViewport(img)) {
      img.src = img.dataset.src;
      img.classList.add('loaded'); // 图片加载完后显示
    }
  });

  // 如果所有图片都加载完了,可以移除滚动事件监听
  if (document.querySelectorAll('.lazy:not(.loaded)').length === 0) {
    window.removeEventListener('scroll', lazyLoad);
  }
}

window.addEventListener('scroll', lazyLoad);
window.addEventListener('resize', lazyLoad); // 处理窗口调整时的加载
优化:使用节流(Throttle)技术

使用 scroll 事件时,滚动操作会触发非常频繁的回调,可能影响性能。因此,可以通过节流(throttle)技术来减少回调的频率。

javascript 复制代码
javascript
复制代码
function throttle(fn, wait) {
  let time = Date.now();
  return function() {
    if ((time + wait - Date.now()) < 0) {
      fn();
      time = Date.now();
    }
  };
}

window.addEventListener('scroll', throttle(lazyLoad, 200)); // 每200ms触发一次lazyLoad
3. <img loading="lazy"> 属性(原生图片懒加载)

最新的 HTML 标准中提供了一个内置的懒加载属性 loading="lazy",可以为 <img><iframe> 元素开启懒加载,无需使用 JavaScript。这是实现懒加载的最简单方法,前提是浏览器支持该特性。

示例:
ini 复制代码
html
复制代码
<img src="image1.jpg" loading="lazy" alt="Lazy image" />

这种方式非常简洁,不过浏览器的支持情况还不完全一致,目前较新的版本的 Chrome、Firefox 等支持这一特性。

4. 模块懒加载(代码拆分)

在现代的 JavaScript 应用(特别是单页面应用中),懒加载不仅可以用于资源(如图片、视频),还可以用于代码模块。通过 Webpack 等打包工具,你可以按需加载代码模块,这样初始页面只加载必要的部分,其他部分在需要时加载。

示例:使用 Webpack 实现模块懒加载
javascript 复制代码
javascript
复制代码
// 某个按钮点击时,才加载某个模块
document.getElementById('loadModuleBtn').addEventListener('click', () => {
  import('./someModule.js').then(module => {
    // 动态加载模块后执行相关操作
    module.doSomething();
  });
});

Webpack 内部会根据 import()someModule.js 拆分成单独的文件,并且在需要的时候按需加载它。

懒加载的应用场景

  1. 图片懒加载:大型图片集、瀑布流布局、图片画廊等场景使用懒加载,减少初始页面加载时间。
  2. 视频/音频懒加载:当用户滚动到视频或音频所在区域时再加载,减少初始带宽消耗。
  3. 模块懒加载:在单页面应用(SPA)中,按需加载 JavaScript 模块,减少初始打包体积,提升首屏性能。
  4. 广告懒加载:广告通常是外部资源,懒加载可以减少对页面的影响,并优化广告展示效果。
  5. 表单或其他资源懒加载:当页面中有多步骤表单时,可以只加载当前步骤的表单元素,其他部分在用户需要时再加载。

懒加载的优点

  • 提升页面性能:懒加载可以减少页面初次加载时的资源数量,加快首屏展示速度,改善用户体验。
  • 减少带宽消耗:只加载用户实际会看到的资源,避免加载多余的内容。
  • 优化大数据场景:对于有大量数据或图像的页面(如电商、社交媒体),懒加载非常有效。

懒加载的缺点

  • 延迟显示:当用户快速滚动到懒加载的内容时,可能会出现短暂的加载延迟,内容需要等异步加载完成后才显示。
  • SEO 影响:如果搜索引擎爬虫无法执行 JavaScript,懒加载的内容可能不会被爬取。但现代搜索引擎对懒加载支持越来越好,影响减小。

总结

懒加载是一种重要的前端优化技术,能有效提升页面的加载性能和用户体验。通过 IntersectionObserver 可以实现高效的懒加载,而在旧版浏览器中则可以通过 scroll 事件实现。同时,HTML5 提供了 <img loading="lazy"> 属性,简化了图片懒加载的实现。无论是图片、视频,还是 JavaScript 模块,懒加载的思路都是按需加载,避免一次性加载过多内容。

4o

您说:

在vue项目中使用模块懒加载

ChatGPT 说:

ChatGPT

在 Vue 项目中,模块懒加载可以通过动态导入和 Vue 路由的异步组件加载实现。懒加载的核心是按需加载 JavaScript 模块,而不是在页面加载时一次性加载所有模块,从而优化页面性能和用户体验。

以下是如何在 Vue 项目中实现模块懒加载的几个常见场景:

1. 路由懒加载

Vue Router 支持通过动态导入的方式实现路由组件的懒加载。这样,只有当用户访问某个路由时,才会加载对应的组件文件,而不是在应用初始化时就加载所有路由的组件。

实现步骤:

假设我们有一个典型的 Vue 项目,其中 HomeAbout 是两个页面,通常你会在路由配置中静态导入组件,如下:

javascript 复制代码
javascript
复制代码
import Home from '@/components/Home.vue';
import About from '@/components/About.vue';

export const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About },
];

实现懒加载的方式

通过使用 Webpack 提供的 import() 函数,进行动态导入:

javascript 复制代码
javascript
复制代码
export const routes = [
  {
    path: '/',
    name: 'Home',
    component: () => import('@/components/Home.vue'),  // 懒加载Home组件
  },
  {
    path: '/about',
    name: 'About',
    component: () => import('@/components/About.vue'), // 懒加载About组件
  },
];
原理:
  • Webpack 会将每个懒加载的模块打包成一个单独的文件(称为代码分块),这些文件只有在用户访问相应路由时才会被加载。
  • 使用 import() 返回一个 Promise,在需要加载组件时动态请求该模块。

2. 组件懒加载

在 Vue 中,你可以按需加载某些组件,而不是在页面加载时一次性加载所有组件。通常你会在大型应用或具有重型组件(如表格、图表等)时使用这个功能。

示例:
xml 复制代码
vue
复制代码
<template>
  <div>
    <h1>Lazy Loading Example</h1>
    <button @click="showComponent = true">加载组件</button>
    <!-- 使用v-if控制懒加载的组件 -->
    <LazyLoadedComponent v-if="showComponent" />
  </div>
</template>

<script>
export default {
  data() {
    return {
      showComponent: false,
    };
  },
  components: {
    LazyLoadedComponent: () => import('@/components/HeavyComponent.vue') // 懒加载组件
  }
};
</script>
解释:
  • 这里我们在 components 选项中使用 import() 函数来动态导入 HeavyComponent.vue,这是一个较重的组件。
  • v-if="showComponent" 控制只有在用户点击按钮时才显示并加载组件,这样可以避免在页面加载时立即加载这个组件。

3. 按需加载 Vuex 模块

在大型应用中,你可能不需要一次性注册所有的 Vuex 模块。可以在某些组件加载时,动态注册 Vuex 模块。

示例:
javascript 复制代码
javascript
复制代码
// store/modules/myModule.js
export default {
  namespaced: true,
  state: {
    count: 0,
  },
  mutations: {
    increment(state) {
      state.count++;
    },
  },
};

// 在某个组件中动态注册 Vuex 模块
export default {
  created() {
    if (!this.$store.hasModule('myModule')) {
      import('@/store/modules/myModule').then(module => {
        this.$store.registerModule('myModule', module.default);
      });
    }
  },
  methods: {
    increment() {
      this.$store.commit('myModule/increment');
    },
  },
};
解释:
  • 在组件创建时,检查是否已经注册了 myModule 模块。如果未注册,则动态加载并注册该 Vuex 模块。
  • 这种方式可以避免初始加载时导入不必要的 Vuex 模块,从而减少应用的初始包大小。

4. 使用 webpackChunkName 为懒加载模块命名

当你在生产环境中使用 Webpack 懒加载时,默认情况下会生成类似 0.js, 1.js 等匿名文件。如果你想要对这些文件进行更友好的命名,可以通过 webpackChunkName 给每个懒加载模块命名。

示例:
javascript 复制代码
javascript
复制代码
export const routes = [
  {
    path: '/',
    name: 'Home',
    component: () => import(/* webpackChunkName: "home" */ '@/components/Home.vue'),
  },
  {
    path: '/about',
    name: 'About',
    component: () => import(/* webpackChunkName: "about" */ '@/components/About.vue'),
  },
];
解释:
  • Webpack 会将生成的懒加载文件命名为 home.jsabout.js,而不是匿名的数字命名,方便调试和识别。

5. 预加载(Preload)与预获取(Prefetch)

除了懒加载,Vue 和 Webpack 还支持预加载预获取技术,帮助你进一步优化资源加载策略。

  • 预加载(Preload) :资源会在父模块加载后立即加载,但其优先级较高,适合页面加载后马上会用到的资源。
  • 预获取(Prefetch) :资源会在浏览器空闲时加载,适合未来可能会用到但不紧急的资源。
使用方式:
javascript 复制代码
javascript
复制代码
// Preload 用法
component: () => import(/* webpackPrefetch: true */ '@/components/About.vue')

// Prefetch 用法
component: () => import(/* webpackPreload: true */ '@/components/Home.vue')
解释:
  • PreloadPrefetch 提供了更灵活的资源加载策略,允许你提前加载即将使用的模块,而不影响首屏性能。

预加载 (Preload)是一种优化网页资源加载的技术,允许浏览器在加载页面的关键资源(如 CSS 和 JavaScript)时,提前加载将要用到的资源。预加载的资源具有较高的优先级,它们会在关键资源加载之后立即开始加载,但不会阻塞关键资源的渲染。

预加载通常用于优化首屏性能,确保关键资源在渲染页面时已经被提前加载,从而减少页面加载时间。

在 Web 项目中,预加载有几种常见的实现方式:

为了优化首屏加载性能,我们可以通过按需加载首屏资源,推迟或懒加载那些不需要立即展示的资源。这种策略可以减少首屏加载时的资源开销,确保用户更快看到页面内容,提升用户体验。

实现首屏只加载需要资源的策略主要有以下几种方法:

1. 路由懒加载(模块按需加载)

在使用单页面应用(SPA)时,比如在 Vue.js 或 React.js 项目中,通常会通过路由系统来切换页面。在首屏渲染时,我们可以通过动态加载非首屏的页面组件,避免一次性加载整个应用的所有页面资源。

Vue.js 中的懒加载:
javascript 复制代码
javascript
复制代码
// 使用 Vue Router 的路由懒加载
const router = new VueRouter({
  routes: [
    {
      path: '/home',
      component: () => import('@/views/Home.vue') // 只在访问时才加载该组件
    },
    {
      path: '/about',
      component: () => import('@/views/About.vue') // 延迟加载,用户访问时才加载
    }
  ]
});
React.js 中的懒加载:
javascript 复制代码
javascript
复制代码
import React, { lazy, Suspense } from 'react';

const Home = lazy(() => import('./Home')); // 首屏页面
const About = lazy(() => import('./About')); // 延迟加载页面

function App() {
  return (
    <Router>
      <Suspense fallback={<div>Loading...</div>}>
        <Switch>
          <Route path="/home" component={Home} />
          <Route path="/about" component={About} />
        </Switch>
      </Suspense>
    </Router>
  );
}

通过路由懒加载,只有当前页面的资源会被加载,而其他页面的组件则在用户导航到对应页面时动态加载。

2. 按需加载 CSS 和 JavaScript

首屏渲染时,我们可以通过按需加载 CSS 和 JavaScript,避免加载整个应用的样式和脚本。可以使用 Webpack 的 splitChunks 进行代码拆分,或者通过动态加载资源的方式控制加载顺序。

动态加载 JavaScript:
javascript 复制代码
javascript
复制代码
// 只在需要时加载某个脚本
function loadScript(url) {
  const script = document.createElement('script');
  script.src = url;
  document.body.appendChild(script);
}

window.addEventListener('DOMContentLoaded', () => {
  loadScript('/path/to/other-script.js'); // 页面加载完成后再加载
});
动态加载 CSS:
ini 复制代码
javascript
复制代码
// 只在需要时加载某个样式文件
function loadCSS(url) {
  const link = document.createElement('link');
  link.rel = 'stylesheet';
  link.href = url;
  document.head.appendChild(link);
}

window.addEventListener('DOMContentLoaded', () => {
  loadCSS('/path/to/other-styles.css'); // 页面加载完成后再加载样式
});

通过动态加载脚本和样式文件,可以只在页面需要时加载额外资源,避免首屏加载过多资源。

3. 图片懒加载

对于首屏不显示的图片,可以使用懒加载技术,即在图片进入视口时才进行加载。这不仅减少了首屏加载的资源,还能减少带宽消耗。

使用 IntersectionObserver 实现懒加载图片:
ini 复制代码
html
复制代码
<img class="lazy" data-src="image1.jpg" alt="Lazy Image 1">
<img class="lazy" data-src="image2.jpg" alt="Lazy Image 2">
ini 复制代码
javascript
复制代码
document.addEventListener("DOMContentLoaded", function() {
  const lazyImages = document.querySelectorAll('.lazy');
  const imageObserver = new IntersectionObserver((entries, observer) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        const img = entry.target;
        img.src = img.dataset.src; // 加载图片
        observer.unobserve(img);   // 停止观察已加载的图片
      }
    });
  });
  lazyImages.forEach(image => imageObserver.observe(image));
});

4. 资源预加载和预获取

对于首屏渲染中马上会用到的资源,可以使用预加载(preload)来加快加载速度,而对于稍后可能需要的资源,则可以使用预获取(prefetch) ,在空闲时加载。

预加载 CSS、JS 或字体:
ini 复制代码
html
复制代码
<link rel="preload" href="/path/to/styles.css" as="style">
<link rel="preload" href="/path/to/script.js" as="script">
<link rel="preload" href="/path/to/font.woff2" as="font" type="font/woff2" crossorigin="anonymous">
预获取非关键资源:
ini 复制代码
html
复制代码
<link rel="prefetch" href="/path/to/large-image.jpg" as="image">
<link rel="prefetch" href="/path/to/secondary-page.js" as="script">

在 HTML 中,你可以使用 <link rel="preload"> 标签来实现资源的预加载。这个标签告诉浏览器,某个资源(如 JavaScript、CSS、字体、图片等)是即将使用的,应该尽早加载。

示例:
ini 复制代码
html
复制代码
<link rel="preload" href="/styles/main.css" as="style">
<link rel="preload" href="/scripts/main.js" as="script">
<link rel="preload" href="/images/banner.jpg" as="image">
解释:
  • href:要预加载的资源路径。
  • as :指定资源的类型,这有助于浏览器正确地管理资源优先级。常见的值有 style(CSS 文件)、script(JavaScript 文件)、image(图片)、font(字体)等。

字体文件也是常见的预加载对象。特别是在页面加载时,需要快速显示文本的场景,提前加载字体可以避免 "FOIT"(Flash of Invisible Text,闪烁的不可见文字)问题。

示例:
bash 复制代码
html
复制代码
<link rel="preload" href="/fonts/my-font.woff2" as="font" type="font/woff2" crossorigin="anonymous">
解释:
  • type="font/woff2" :指定字体文件的格式。
  • crossorigin="anonymous" :对于跨域的字体请求,设置 crossorigin 属性,确保浏览器能够正确地加载该资源。

3. 使用 Webpack 的 Preload 插件

在使用 Webpack 时,你可以通过动态导入 JavaScript 模块,同时为某些模块添加预加载功能。这可以确保在当前模块加载时,预加载未来可能用到的模块,以便用户需要时快速加载。

Webpack 提供了 PreloadPrefetch 注释,分别用于加载即将用到的资源和可能未来用到的资源。

使用 Webpack 实现预加载

假设你在 Vue 项目或 React 项目中使用 Webpack,你可以通过 import() 来动态加载模块,并添加预加载注释:

java 复制代码
javascript
复制代码
// Preload example: 该模块会在父模块加载后立即加载
import(/* webpackPreload: true */ './myComponent.js').then(module => {
  // 使用加载后的模块
  module.default();
});
解释:
  • /* webpackPreload: true */ :这是 Webpack 的魔法注释,告诉 Webpack 要预加载这个模块。在加载当前模块的同时,浏览器会优先加载这个预加载的模块,以便在稍后更快地使用。

为了实现页面上使用 MD5 值来判断是否使用接口数据或缓存数据的功能,你需要遵循以下步骤:

楼层式加载

实现步骤概述:

  1. 请求数据并生成 MD5 哈希值:请求接口数据后,对数据内容生成 MD5 哈希值。
  2. 缓存数据与 MD5 :将数据和 MD5 哈希值一起存入缓存(比如 localStorage)。
  3. 判断是否使用缓存数据:在每次进入页面时,先检查缓存中的 MD5 值是否与接口返回的 MD5 匹配。如果匹配,则使用缓存数据;如果不匹配,则重新请求接口数据并更新缓存。
相关推荐
Front思14 分钟前
vue3中el-input在form表单按下回车刷新页面
前端·javascript·vue.js
Minyy1116 分钟前
小程序-使用npm包
前端·小程序·npm·node.js
牧小七18 分钟前
ElementPlus---Timeline 时间线组件使用示例
前端·javascript·vue.js·element-plus·element-plus组件
fishmemory7sec21 分钟前
Electron 使用 Nodemon 配置自动重启
前端·javascript·electron
Mrs_Lupin21 分钟前
npm与包
前端·npm·node.js
潜心专研的小张同学24 分钟前
pnpm依赖安装失败解决|pnpm项目从一个文件夹复制到另一个文件夹运行失败问题解决-以vbenAdmin项目为例
前端·javascript·vscode·npm·vue·pnpm
weixin_531804241 小时前
泛型中的通配符<?>、<? extends T>、<? super T>的使用场景。ArrayList与LinkedList的区别及适用场景。
java·前端·javascript
@AfeiyuO1 小时前
Angular基础学习(入门 --> 入坑)
前端·angular.js
惜.己1 小时前
CSS样式基础样式选择器(案例+代码实现+效果图)
开发语言·前端·css·vscode·html·html5
二手的程序员1 小时前
网络抓包04 - SSLSocket
java·开发语言·前端·算法·网络安全