屏幕宽度变化时切换对应图片数组的React实现方案
React 实现横竖屏自动切换对应图片数组渲染方案
实现思路
核心逻辑是实时判断当前屏幕方向,横屏状态下渲染landscape_images数组内容,竖屏状态下渲染portrait_images数组内容,监听事件做防抖优化,同时做好组件卸载时的内存清理,避免性能问题。
第一步:定义基础图片数组
先按照需求定义两个场景对应的图片数组,元素存储图片资源路径和必要的描述信息:
// 横屏场景适配的宽分辨率图片数组 const landscape_images = [ { id: 1, src: '/imgs/landscape/home-banner.jpg', alt: '首页横屏主banner' }, { id: 2, src: '/imgs/landscape/activity-banner.jpg', alt: '活动区横屏banner' }, { id: 3, src: '/imgs/landscape/recommend-banner.jpg', alt: '推荐区横屏banner' } ] // 竖屏场景适配的长尺寸图片数组 const portrait_images = [ { id: 1, src: '/imgs/portrait/home-banner.jpg', alt: '首页竖屏主banner' }, { id: 2, src: '/imgs/portrait/activity-banner.jpg', alt: '活动区竖屏banner' }, { id: 3, src: '/imgs/portrait/recommend-banner.jpg', alt: '推荐区竖屏banner' } ]
第二步:React组件核心实现
用函数组件+Hooks实现,优先用性能更好的matchMedia监听屏幕方向变化,同时加resize事件做兼容兜底,加入防抖避免频繁触发重渲染:
import { useState, useEffect } from 'react' import './AdaptiveImage.css' export default function AdaptiveImageRender() { // 初始化时直接判断当前屏幕方向,避免首屏闪切 const [isLandscape, setIsLandscape] = useState(() => window.innerWidth > window.innerHeight) useEffect(() => { let debounceTimer = null // 方向变化处理逻辑,加200ms防抖 const updateOrientation = () => { clearTimeout(debounceTimer) debounceTimer = setTimeout(() => { setIsLandscape(window.innerWidth > window.innerHeight) }, 200) } // 优先使用matchMedia监听屏幕方向,性能优于resize监听 const orientationMatcher = window.matchMedia('(orientation: landscape)') // 兼容新旧浏览器的事件绑定写法 if (orientationMatcher.addEventListener) { orientationMatcher.addEventListener('change', updateOrientation) } else { orientationMatcher.addListener(updateOrientation) } // 兜底监听resize事件,覆盖PC端拖拽调整窗口、异形屏判断不准的场景 window.addEventListener('resize', updateOrientation) // 组件卸载时清除所有监听和定时器,防止内存泄漏 return () => { clearTimeout(debounceTimer) if (orientationMatcher.removeEventListener) { orientationMatcher.removeEventListener('change', updateOrientation) } else { orientationMatcher.removeListener(updateOrientation) } window.removeEventListener('resize', updateOrientation) } }, []) // 根据当前方向取对应要渲染的图片数组 const renderImageList = isLandscape ? landscape_images : portrait_images return ( <div className="img-container"> {renderImageList.map(imgItem => ( <img key={imgItem.id} src={imgItem.src} alt={imgItem.alt} className="adaptive-img" /> ))} </div> ) }
第三步:配套CSS样式
写基础样式保证图片自适应容器,不会出现布局溢出:
/* 重置body默认边距,保证全屏适配 */ body { margin: 0; padding: 0; } .img-container { width: 100%; } .adaptive-img { width: 100%; display: block; /* 根据业务需求调整填充模式,cover为铺满容器裁剪多余部分,contain为完整显示图片 */ object-fit: cover; }
可选优化点
- 如果需要固定断点判断(比如宽度大于768px就算横屏场景,适配平板设备),可以把判断逻辑里的
window.innerWidth > window.innerHeight替换为window.innerWidth >= 768即可 - 如果项目里用了React Router等路由库,注意这个自适应组件要放在路由外层,保证路由切换时方向监听不会重复绑定
- 图片资源可以加懒加载属性,给
<img>标签加上loading="lazy",减少首屏加载压力
内容的提问来源于stack exchange,提问作者user16301464
相关产品推荐
相关产品推荐

