动态显示相同项目的照片,如果只有一张照片则隐藏轮播
Dynamically display photos of same item and hide carousel if there is only one photo
在 React 应用程序中,我显示每个项目的 1-5 张照片。所有照片都在 Node
下的文件夹中,所以我显示它们的方式是使用它们的 url,即 http://10.1.1.1:3000/01-0001.JPG
所以,我没有发出 http 请求来获取它们。
问题是:
无法知道每件商品有多少张照片。例如,一件商品可能有 5 张照片,而另一件商品只有一张照片。文件名的格式是这样的:01-0001.JPG, 01-0001.1.JPG, 01-0001.2.JPG
所以,我现在做的是:
const Item1 = () => {
return (
<img src={`${process.env.REACT_APP_NODE_SERVER}/${item.No}.JPG`} onError={this.addDefaultSrc} alt='1'></img>
)
}
const Item2 = () => {
return (
<img src={`${process.env.REACT_APP_NODE_SERVER}/${item.No}.1.JPG`} onError={this.addDefaultSrc} alt='2'></img>
)
}
const Item3 = () => {
return (
<img src={`${process.env.REACT_APP_NODE_SERVER}/${item.No}.2.JPG`} onError={this.addDefaultSrc} alt='3'></img>
)
}
我用这个功能在没有照片的时候显示一张虚拟照片
addDefaultSrc(ev) {
ev.target.src = `${process.env.REACT_APP_NODE_SERVER}/notfound.png`;
ev.target.onerror = null;
}
这是一个糟糕的解决方案,因为我不希望客户看到虚拟图片,相反,客户应该只看到每件商品的真实照片数量。
我正在使用 react-multi-carousel
<Carousel
responsive={responsive}
swipeable={false}
draggable={false}
showDots={true}
ssr={false} // means to render carousel on server-side.
infinite={false}
autoPlay={false}
autoPlaySpeed={1000}
keyBoardControl={true}
customTransition="all .5"
transitionDuration={500}
containerClass="carousel-container"
removeArrowOnDeviceType={["tablet", "mobile"]}
deviceType={this.props.deviceType}
dotListClass="custom-dot-list-style"
itemClass="carousel-item-padding-40-px">
<div><Item1 /></div>
<div><Item2 /></div>
<div><Item3 /></div>
</Carousel>
如有任何帮助,我们将不胜感激。
我认为您应该遍历图像,将初始样式设置为 display: none
,等待所有回调并在一切完成后计算适当的状态。
例子
const { useState, useEffect } = React;
const random = () => Math.floor(Math.random() * 5 + 5);
const getImages = () => Promise.resolve(Array(random()).fill(0).map((pr, index) => {
const id = index + 750;
return {
id,
url: `https://i.picsum.photos/id/${id}/100/100.jpg`,
loaded: false,
error: false,
alt: id
}
}))
const Images = ({onComplete}) => {
const [images, setImages] = useState([]);
const [allLoaded, setLoaded] = useState(false);
useEffect(() => {
let isUnmounted = false;
getImages()
.then(images => {
if(isUnmounted) {
return;
}
setImages(images);
})
return () => {
isUnmounted = true;
}
}, [])
useEffect(() => {
let isUnmounted = false;
const loadedImagesCount = images.reduce((acc, image) => acc + Number(image.error) + Number(image.loaded), 0);
if(images.length === loadedImagesCount) {
setTimeout(() => {
if(isUnmounted) {
return;
}
setLoaded(true);
onComplete();
}, 500);
}
return () => {
isUnmounted = true;
}
}, [images])
const onError = id => {
setImages(images => {
const imageIndex = images.findIndex(image => image.id ===id)
const image = images[imageIndex];
return [
...images.slice(0, imageIndex),
{
...image,
error: true
},
...images.slice(imageIndex + 1)
]
})
}
const onLoad = id => {
setImages(images => {
const imageIndex = images.findIndex(image => image.id ===id)
const image = images[imageIndex];
return [
...images.slice(0, imageIndex),
{
...image,
loaded: true
},
...images.slice(imageIndex + 1)
]
})
}
const loadedImagesCount = images.reduce((acc, image) => acc + Number(image.loaded), 0)
if(allLoaded && [0, 1].includes(loadedImagesCount)) {
return 'No images or only one image - hidden'
}
return <React.Fragment>
{images.map(({id, loaded, error, url, alt}) => <img key={id} src={url} className={`image ${error ? 'image--error' : null} ${allLoaded && loaded ? 'image--loaded' : null}`} onLoad={() => onLoad(id)} onError={() => onError(id)} alt={alt}/>)}
</React.Fragment>
}
const App = () => {
const [loading, setLoading] = useState(true);
const onComplete = () => {
setLoading(false);
}
return <div>
{loading ? 'Loading...' : null}
<Images onComplete={onComplete}/>
</div>
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
.image {
display: none;
}
.image--error {
display: none;
}
.image--loaded {
display: inline;
}
<script src="https://unpkg.com/react/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<div id="root"></div>
在 React 应用程序中,我显示每个项目的 1-5 张照片。所有照片都在 Node
下的文件夹中,所以我显示它们的方式是使用它们的 url,即 http://10.1.1.1:3000/01-0001.JPG
所以,我没有发出 http 请求来获取它们。
问题是:
无法知道每件商品有多少张照片。例如,一件商品可能有 5 张照片,而另一件商品只有一张照片。文件名的格式是这样的:01-0001.JPG, 01-0001.1.JPG, 01-0001.2.JPG
所以,我现在做的是:
const Item1 = () => {
return (
<img src={`${process.env.REACT_APP_NODE_SERVER}/${item.No}.JPG`} onError={this.addDefaultSrc} alt='1'></img>
)
}
const Item2 = () => {
return (
<img src={`${process.env.REACT_APP_NODE_SERVER}/${item.No}.1.JPG`} onError={this.addDefaultSrc} alt='2'></img>
)
}
const Item3 = () => {
return (
<img src={`${process.env.REACT_APP_NODE_SERVER}/${item.No}.2.JPG`} onError={this.addDefaultSrc} alt='3'></img>
)
}
我用这个功能在没有照片的时候显示一张虚拟照片
addDefaultSrc(ev) {
ev.target.src = `${process.env.REACT_APP_NODE_SERVER}/notfound.png`;
ev.target.onerror = null;
}
这是一个糟糕的解决方案,因为我不希望客户看到虚拟图片,相反,客户应该只看到每件商品的真实照片数量。
我正在使用 react-multi-carousel
<Carousel
responsive={responsive}
swipeable={false}
draggable={false}
showDots={true}
ssr={false} // means to render carousel on server-side.
infinite={false}
autoPlay={false}
autoPlaySpeed={1000}
keyBoardControl={true}
customTransition="all .5"
transitionDuration={500}
containerClass="carousel-container"
removeArrowOnDeviceType={["tablet", "mobile"]}
deviceType={this.props.deviceType}
dotListClass="custom-dot-list-style"
itemClass="carousel-item-padding-40-px">
<div><Item1 /></div>
<div><Item2 /></div>
<div><Item3 /></div>
</Carousel>
如有任何帮助,我们将不胜感激。
我认为您应该遍历图像,将初始样式设置为 display: none
,等待所有回调并在一切完成后计算适当的状态。
例子
const { useState, useEffect } = React;
const random = () => Math.floor(Math.random() * 5 + 5);
const getImages = () => Promise.resolve(Array(random()).fill(0).map((pr, index) => {
const id = index + 750;
return {
id,
url: `https://i.picsum.photos/id/${id}/100/100.jpg`,
loaded: false,
error: false,
alt: id
}
}))
const Images = ({onComplete}) => {
const [images, setImages] = useState([]);
const [allLoaded, setLoaded] = useState(false);
useEffect(() => {
let isUnmounted = false;
getImages()
.then(images => {
if(isUnmounted) {
return;
}
setImages(images);
})
return () => {
isUnmounted = true;
}
}, [])
useEffect(() => {
let isUnmounted = false;
const loadedImagesCount = images.reduce((acc, image) => acc + Number(image.error) + Number(image.loaded), 0);
if(images.length === loadedImagesCount) {
setTimeout(() => {
if(isUnmounted) {
return;
}
setLoaded(true);
onComplete();
}, 500);
}
return () => {
isUnmounted = true;
}
}, [images])
const onError = id => {
setImages(images => {
const imageIndex = images.findIndex(image => image.id ===id)
const image = images[imageIndex];
return [
...images.slice(0, imageIndex),
{
...image,
error: true
},
...images.slice(imageIndex + 1)
]
})
}
const onLoad = id => {
setImages(images => {
const imageIndex = images.findIndex(image => image.id ===id)
const image = images[imageIndex];
return [
...images.slice(0, imageIndex),
{
...image,
loaded: true
},
...images.slice(imageIndex + 1)
]
})
}
const loadedImagesCount = images.reduce((acc, image) => acc + Number(image.loaded), 0)
if(allLoaded && [0, 1].includes(loadedImagesCount)) {
return 'No images or only one image - hidden'
}
return <React.Fragment>
{images.map(({id, loaded, error, url, alt}) => <img key={id} src={url} className={`image ${error ? 'image--error' : null} ${allLoaded && loaded ? 'image--loaded' : null}`} onLoad={() => onLoad(id)} onError={() => onError(id)} alt={alt}/>)}
</React.Fragment>
}
const App = () => {
const [loading, setLoading] = useState(true);
const onComplete = () => {
setLoading(false);
}
return <div>
{loading ? 'Loading...' : null}
<Images onComplete={onComplete}/>
</div>
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
.image {
display: none;
}
.image--error {
display: none;
}
.image--loaded {
display: inline;
}
<script src="https://unpkg.com/react/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<div id="root"></div>