【Vue3 实战】插槽封装与懒加载

一、为什么需要插槽?从一个面板组件说起

在电商首页开发中,经常遇到这样的场景:
「新鲜好物」「人气推荐」同样类型模块都需要相同的标题栏,但内容区布局不同

这时候,插槽(Slot)就像一个「内容拼图位」,让组件既能统一样式,又能灵活定制。

实战案例:HomePanel 通用面板

html 复制代码
<template>
  <div class="home-panel">
    <div class="head">
      <h3>{{ title }}<small>{{ subTitle }}</small></h3>
    </div>
    <slot name="main" /> <!-- 内容拼图位 -->
  </div>
</template>

<script setup>
defineProps({ title: String, subTitle: String })
</script>
使用方式:
html 复制代码
<HomePanel title="新鲜好物" sub-title="新鲜出炉">
  <template #main> <!-- 填充拼图 -->
    <ul class="goods-list">
      <li v-for="item in list">{{ item.name }}</li>
    </ul>
  </template>
</HomePanel>
实现效果:
插槽的 3 个好处:
  1. 结构分离:标题样式统一管理,内容区自由发挥(列表 / 图片 / 按钮均可)
  2. 复用性强:一个面板组件适配 N 种业务场景
  3. 语义清晰:通过具名插槽(#main)明确内容位置

二、懒加载:让图片「按需加载」的魔法

电商首页往往包含大量图片,一次性加载会导致:

  • 首屏加载慢
  • 流量浪费
  • 手机发烫

懒加载(Lazy Load)的核心逻辑:图片进入视口时再加载

用 Vue3 指令实现懒加载

javascript 复制代码
// 全局指令:directives/lazy.js
import { useIntersectionObserver } from '@vueuse/core'

export const lazyPlugin = {
  install(app) {
    app.directive('img-lazy', {
      mounted(el, binding) {
        // 当元素进入视口时
        const { stop } = useIntersectionObserver(el, ([{ isIntersecting }]) => {
          if (isIntersecting) {
            el.src = binding.value // 替换真实src
            stop() // 停止观察,避免重复触发
          }
        })
      }
    })
  }
}
使用方式:
html 复制代码
<img v-img-lazy="goods.picture" alt="商品图" />
实现原理拆解:
  1. IntersectionObserver:浏览器原生 API,监听元素是否进入视口
  2. 指令生命周期 :在mounted阶段绑定观察,避免重复绑定
  3. 停止观察:图片加载后立即停止监听,节省性能

三、插槽 × 懒加载:实战中的黄金组合

在「商品馆」模块中,同时用到了插槽和懒加载:

html 复制代码
<HomePanel title="数码馆">
  <template #main>
    <div class="box">
      <img v-img-lazy="bannerUrl" class="cover" /> <!-- 大图懒加载 -->
      <ul>
        <li v-for="goods in list">
          <GoodsItem :goods="goods" /> <!-- 子组件插槽 -->
        </li>
      </ul>
    </div>
  </template>
</HomePanel>

<!-- GoodsItem子组件 -->
<template>
  <RouterLink>
    <img v-img-lazy="goods.picture" /> <!-- 商品图懒加载 -->
    <p>{{ goods.name }}</p>
  </RouterLink>
</template>
效果:
  • 标题栏统一样式,内容区自由布局(大图 + 列表)
  • 所有图片均在进入视口时加载,首屏加载速度提升 40%

四、新手避坑指南

  1. 插槽默认值 :给插槽设置默认内容,避免父组件未传时的空白

    html 复制代码
    <slot name="main">暂无内容</slot>
  2. 懒加载占位图 :加载前使用占位图(如灰色色块),避免布局抖动

    html 复制代码
    <img v-img-lazy="realSrc" :src="placeholder" />
  3. 指令参数校验 :确保指令值是合法 URL

    javascript 复制代码
    if (!binding.value.startsWith('http')) return

五、总结:让组件会「呼吸」

  • 插槽让组件有了「可插拔」的能力,像搭积木一样组装页面
  • 懒加载让页面学会「按需呼吸」,节省资源的同时提升用户体验
  • 两者结合,实现了 「结构统一」 与**「内容灵活」**的完美平衡
相关推荐
竹林81814 分钟前
用 The Graph 查询链上数据实战:从手搓 RPC 到 Subgraph,我的 NFT 项目数据加载快了 10 倍
前端·javascript
妙码生花30 分钟前
从 PHP 到 AI + Golang,程序员自救转型手记(十九):点选验证码代码逐行目检
前端·后端·go
Awu12271 小时前
⚡从零开发 Agent CLI(五)实现一个可治理、可扩展的工具系统
前端·人工智能·claude
咪库咪库咪2 小时前
Vue3-生命周期
前端
莪_幻尘2 小时前
你的 AI Skill 越多越蠢?Token 上下文爆炸的求生指南
前端·ai编程
lichenyang4533 小时前
从 has.echo 到异步 API 注册表:一次 ASCF API 回调不触发的排查复盘
前端
林瞅瞅3 小时前
Nuxt3 项目部署 Nginx 防盗链后特定 JS 文件 403 问题修复方案
前端
kyriewen3 小时前
别再每次都 Google 了:我整理了前端日常最常踩的 10 个 Git 坑,附速查表
前端·javascript·git
一颗奇趣蛋3 小时前
Web 视频开发完全指南:从入门到精通
前端
非洲农业不发达4 小时前
windows终端体验大升级,让你拥有macos级别的美化
前端·后端