如何从Firebase Storage获取URL数组并渲染图片画廊?
从Firebase Storage获取图片并实现画廊展示
我想从Firebase Storage获取已上传的图片,然后以网格画廊形式展示(参考整齐排列的图片网格,每张图大小一致、带间距)。目前我写了获取图片URL的代码,但刚接触JS/TS,不知道怎么渲染URL数组里的图片,希望得到帮助。
现有获取URL的代码
function listAll() :{ url: string; }[]{ const storageRef = firebase.storage().ref(); let listRef = storageRef.child('/'); const accum: { url: string; }[] = []; listRef.listAll() .then((res) => { res.prefixes.forEach((folderRef) => { // All the prefixes under listRef. // You may call listAll() recursively on them. }); res.items.forEach((itemRef) => { itemRef.getDownloadURL().then((url) => { console.log(url); accum.push({ url }) }) }); }).catch((error) => { console.log('Errors while downloading => ', error); }); return accum }
现有样式表(React Native)
container: { flex: 1, backgroundColor: '#fff', paddingTop: Platform.OS === "android" ? Constants.statusBarHeight:0, }, imgParent: { flex: 1, justifyContent: "space-around", flexDirection: "row", alignItems:"center", flexWrap: 'wrap', backgroundColor: '#fff', }, imgElements: { margin:10, width: 150, height:150, },
解决方案
1. 修复图片URL获取函数
原函数的核心问题是异步操作未完成就返回数组:listAll()和getDownloadURL()都是异步Promise,直接返回accum时数组还是空的。改成异步函数,用async/await处理:
async function listAll(): Promise<{ url: string; }[]> { const storageRef = firebase.storage().ref(); const listRef = storageRef.child('/'); const accum: { url: string; }[] = []; try { const res = await listRef.listAll(); // 如需遍历子文件夹,取消下方注释并使用递归函数 // res.prefixes.forEach(async (folderRef) => { // const folderImages = await listAllFromFolder(folderRef); // accum.push(...folderImages); // }); // 批量获取所有图片的下载链接 const urlPromises = res.items.map(itemRef => itemRef.getDownloadURL()); const urls = await Promise.all(urlPromises); urls.forEach(url => accum.push({ url })); return accum; } catch (error) { console.log('Errors while downloading => ', error); return []; } } // 可选:递归获取子文件夹内的图片 async function listAllFromFolder(folderRef: firebase.storage.Reference): Promise<{ url: string; }[]> { const accum: { url: string; }[] = []; const res = await folderRef.listAll(); const urlPromises = res.items.map(itemRef => itemRef.getDownloadURL()); const urls = await Promise.all(urlPromises); urls.forEach(url => accum.push({ url })); // 递归处理子文件夹 for (const subFolderRef of res.prefixes) { const subFolderImages = await listAllFromFolder(subFolderRef); accum.push(...subFolderImages); } return accum; }
2. 在React Native组件中渲染画廊
用useState存储图片URL数组,useEffect调用异步函数获取数据,遍历数组渲染图片:
import React, { useState, useEffect } from 'react'; import { View, Image, StyleSheet, Platform, Constants } from 'react-native'; export default function ImageGallery() { const [images, setImages] = useState<{ url: string; }[]>([]); useEffect(() => { const fetchImages = async () => { const imageUrls = await listAll(); setImages(imageUrls); }; fetchImages(); }, []); return ( <View style={styles.container}> <View style={styles.imgParent}> {images.map((image, index) => ( <Image key={index} style={styles.imgElements} source={{ uri: image.url }} resizeMode="cover" // 保持图片比例,避免拉伸变形 /> ))} </View> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', paddingTop: Platform.OS === "android" ? Constants.statusBarHeight : 0, }, imgParent: { flex: 1, justifyContent: "space-around", flexDirection: "row", alignItems: "center", flexWrap: 'wrap', backgroundColor: '#fff', }, imgElements: { margin: 10, width: 150, height: 150, borderRadius: 8, // 可选:添加圆角,贴近示例效果 }, });
关键说明
- 用
async/await确保异步请求完成后再更新组件状态 - 用
map遍历URL数组,为每张图渲染Image组件,必须添加唯一key resizeMode="cover"可让图片按比例填充容器,避免拉伸- 需要包含子文件夹图片时,取消递归函数的注释即可
内容的提问来源于stack exchange,提问作者bixtico
相关产品推荐
相关产品推荐

