You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在MUI Autocomplete的Avatar组件中实现图片懒加载?

解决方案

针对MUI Autocomplete加载大量Avatar图片时的不必要加载问题,有两种实用方案:

方案一:使用虚拟列表(推荐)

Autocomplete默认会渲染所有选项,导致500+个Avatar一次性加载。虚拟列表只会渲染当前视口内的选项,从根源上避免无效图片请求,同时提升下拉菜单的渲染性能。

实现步骤(结合react-window)

  1. 安装依赖:
npm install react-window
  1. 代码示例:
import React from 'react';
import Autocomplete from '@mui/material/Autocomplete';
import TextField from '@mui/material/TextField';
import Avatar from '@mui/material/Avatar';
import { FixedSizeList as List } from 'react-window';

// 你的500+条选项数据
const options = Array.from({ length: 500 }, (_, i) => ({
  id: i,
  name: `Option ${i}`,
  avatarUrl: `https://example.com/avatar/${i}.jpg`
}));

// 渲染单个选项
const renderOption = (props, option) => {
  const { style } = props;
  return (
    <div 
      style={{ 
        ...style, 
        display: 'flex', 
        alignItems: 'center', 
        padding: '8px 16px',
        cursor: 'pointer'
      }}
    >
      <Avatar src={option.avatarUrl} alt={option.name} />
      <span style={{ marginLeft: 12 }}>{option.name}</span>
    </div>
  );
};

// 自定义列表容器,集成虚拟列表
const ListboxComponent = (props) => {
  const { children, ...other } = props;
  return (
    <div 
      {...other} 
      style={{ 
        maxHeight: 400, 
        overflow: 'auto',
        borderTop: '1px solid #e0e0e0'
      }}
    >
      <List
        height={400}
        itemCount={options.length}
        itemSize={48} // 每个选项的高度
        width="100%"
      >
        {renderOption}
      </List>
    </div>
  );
};

export default function VirtualizedAutocomplete() {
  return (
    <Autocomplete
      options={options}
      renderInput={(params) => (
        <TextField {...params} label="选择选项" variant="outlined" />
      )}
      ListboxComponent={ListboxComponent}
    />
  );
}

原理

虚拟列表FixedSizeList只会渲染当前滚动视口内的选项,只有可见的Avatar会被创建并加载图片,未进入视口的选项不会生成DOM节点,自然不会触发图片请求。


方案二:基于Intersection Observer的懒加载

如果不想引入虚拟列表依赖,可以用浏览器原生的Intersection Observer API,监听Avatar是否进入下拉菜单的视口,仅在可见时加载真实图片。

代码示例

import React, { useEffect, useRef } from 'react';
import Autocomplete from '@mui/material/Autocomplete';
import TextField from '@mui/material/TextField';
import Avatar from '@mui/material/Avatar';

const options = Array.from({ length: 500 }, (_, i) => ({
  id: i,
  name: `Option ${i}`,
  avatarUrl: `https://example.com/avatar/${i}.jpg`
}));

// 自定义懒加载Avatar组件
const LazyAvatar = ({ src, alt }) => {
  const imgRef = useRef(null);
  // 空白占位图(避免加载失败的图标)
  const placeholderSrc = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';

  useEffect(() => {
    // 获取Autocomplete的下拉菜单容器作为观察根节点
    const listboxRoot = document.querySelector('.MuiAutocomplete-listbox');
    if (!listboxRoot || !imgRef.current) return;

    const observer = new IntersectionObserver(
      (entries) => {
        entries.forEach(entry => {
          if (entry.isIntersecting) {
            // 元素可见时加载真实图片
            imgRef.current.src = src;
            // 停止观察该元素
            observer.unobserve(entry.target);
          }
        });
      },
      { root: listboxRoot, rootMargin: '20px' } // 提前20px开始加载
    );

    observer.observe(imgRef.current);

    // 组件卸载时清理观察器
    return () => observer.unobserve(imgRef.current);
  }, [src]);

  return <Avatar ref={imgRef} src={placeholderSrc} alt={alt} />;
};

export default function LazyLoadAutocomplete() {
  return (
    <Autocomplete
      options={options}
      renderOption={(props, option) => (
        <li 
          {...props} 
          style={{ 
            display: 'flex', 
            alignItems: 'center', 
            padding: '8px 16px'
          }}
        >
          <LazyAvatar src={option.avatarUrl} alt={option.name} />
          <span style={{ marginLeft: 12 }}>{option.name}</span>
        </li>
      )}
      renderInput={(params) => (
        <TextField {...params} label="选择选项" variant="outlined" />
      )}
    />
  );
}

原理

  • 初始给Avatar设置空白占位图,不加载真实图片
  • 通过Intersection Observer监听Avatar是否进入下拉菜单的视口范围
  • 当元素进入视口时,替换为真实图片地址并停止观察

内容的提问来源于stack exchange,提问作者suman j

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 05:45:03