封装一个轮播图组件--支持阿拉伯语使用习惯
轮播图作为现代网页设计中的一个重要组成部分,为页面增添了动感与视觉吸引力。当这一组件遇到支持不同文化习惯的需求时,比如阿拉伯语的从右到左阅读习惯,轮播图的设计和实现就需要更多的细节考虑。在这篇文章中,将详细介绍如何封装一个既符合通用设计又能够满足专门需求的轮播图组件。
首先,让我们了解一下阿拉伯语使用习惯。与英文等使用从左到右书写习惯的语言不同,阿拉伯语的书写和阅读方向是从右到左。因此,在处理标准的轮播逻辑时,需要进行适用于阿拉伯语的反向处理。
接下来,将分解我们封装的轮播图组件代码,逐步理解其功能和实现方式。
组件库和样式引入
一开始,我们引入了react
,利用react
的声明式特性和组件化思想创建我们的轮播图组件。接着引入react-slick
和相关样式文件,react-slick
是一个专为React开发的轮播图库。它提供了丰富的接口和完整的功能,能够帮助我们快速实现强大的轮播功能。styled-components
则用于扩展和定制已有样式,实现自定义组件。
样式组件定义
通过styled-components
创建了一个名为ISlider
的样式组件,该组件在Slider
的基础上进行样式的定制。通过props
,我们可以动态设置轮播图高度及小点(pagination dots)的位置。
jsx
const ISlider = styled(Slider)`
& {
.slick-list {
height: ${props => props.height}px!important;
}
.slick-dots {
top: ${props => props.dotsPosition}%!important;
}
}
`;
这确保了轮播的灵活性和适应性,允许组件使用者根据具体需求定制轮播图的外观。
轮播图组件定义
定义了一个CustomCarousel
函数组件,接收一个包含默认值的props
。picList
存放图片数据,height
、width
用于设置轮播图的尺寸,settings
用于定制轮播图的行为,margin
和containerStyle
用于设置容器样式,dotsPosition
指定分页器位置。
组件内部,首先处理了settings.rtl
,即从右到左阅读设置,根据这个设置将图片数组picList
排序,以适配不同文化的阅读习惯。
默认轮播图属性
定义了一个名为defaultSettings
的默认配置对象,涉及滑动显示、自动播放、无限循环等多种轮播属性。特别地,在appendDots
中,针对轮播图的小点,设置了自定义的分页器样式。
jsx
const defaultSettings = {
// ...
appendDots: dots => {
if(!dots?.length) return <></>;
return (
<div style={{ /* 分页器的样式 */ }}>
{dots.map( /* 处理每个分页点的样式 */ )}
</div>
)
},
};
组件返回
组件最终返回的是一个带有封装后的ISlider
和图片列表的div
。通过展开操作符...
应用了我们的配置到ISlider
组件。
jsx
return (
<div style={{
height,
width,
overflow: 'hidden',
margin,
...containerStyle,
}}>
<ISlider {..._settings} height={height} dotsPosition={dotsPosition}>
{sortedPicList.map(
(pic, idx) => {
return (
<div
className={`img-container ${_settings.className}-img-container`}
key={pic.name+idx}
>
<img
src={pic.url}
alt={pic.name}
style={{background: '#fff'}}
onError={(e)=>{
const {target} = e;
if(target instanceof HTMLImageElement){
target.setAttribute('height', target.style.height);
target.setAttribute('visibility', target.style.visibility);
target.style.height = '0px';
target.style.visibility = 'none';
}
}}
onLoad={(e)=>{
const {target} = e;
if(target instanceof HTMLImageElement && target.dataSet){
const { height, visibility } = target.dataSet;
target.style.height = height ?? 'auto';
target.style.visibility = visibility ?? 'auto';
}
}}
/>
</div>
)
}
)}
</ISlider>
</div>
);
图片渲染与异常处理
在map
循环内部,为每个图片创建了div
容器,并设置了响应图片加载错误onError
以及加载完成onLoad
时的处理逻辑,以实现更加健壮的组件。
jsx
<div style={{
display:'flex',
justifyContent: 'center',
}}>
{dots.map(
(dot, idx) => {
const {props:{className:dotCls}} = dot;
if(dotCls && dotCls.match(/active/)) {
return <span
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
width: 24,
height: 6,
background: '#C4C5CA',
borderRadius: 3,
marginRight: 6,
}}
key={'dot'+idx+dotCls}
>{dot}</span>
} else {
return <span
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
width: 6,
height: 6,
background: '#C4C5CA',
borderRadius: 3,
marginRight: 6,
}}
key={'dot'+idx+dotCls}
>{dot}</span>
}
}
)}
</div>
封装组件的完整代码
jsx
import React from "react";
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
import Slider from "react-slick";
import styled from "styled-components";
import "./index.less";
const ISlider = styled(Slider)`
& {
.slick-list {
height: ${props => props.height}px!important;
}
.slick-dots {
top: ${props => props.dotsPosition}%!important;
}
}
`;
function CustomCarousel(props) {
const {
picList = [],
height = 'auto',
width = '100%',
settings = {},
margin = '0 auto',
containerStyle = {},
dotsPosition = 65,
} = props;
const sortedPicList = settings.rtl ? [...picList].reverse() : [...picList];
const defaultSettings = {
className: 'custom-carousel',
style:{height, position: 'relative'},
dots: false,
autoplay: false,
infinite: true,
arrows: false,
pauseOnDotsHover: false,
pauseOnHover: true,
speed: 500,
slidesToShow: 1,
slidesToScroll: 1,
rtl: false,
appendDots: dots => {
if(!dots?.length) return <></>;
return (
<div style={{
display:'flex',
justifyContent: 'center',
}}>
{dots.map(
(dot, idx) => {
const {props:{className:dotCls}} = dot;
if(dotCls && dotCls.match(/active/)) {
return <span
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
width: 24,
height: 6,
background: '#C4C5CA',
borderRadius: 3,
marginRight: 6,
}}
key={'dot'+idx+dotCls}
>{dot}</span>
} else {
return <span
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
width: 6,
height: 6,
background: '#C4C5CA',
borderRadius: 3,
marginRight: 6,
}}
key={'dot'+idx+dotCls}
>{dot}</span>
}
}
)}
</div>
)
},
};
const _settings = { ...defaultSettings, ...settings };
return (
<div style={{
height,
width,
overflow: 'hidden',
margin,
...containerStyle,
}}>
<ISlider {..._settings} height={height} dotsPosition={dotsPosition}>
{sortedPicList.map(
(pic, idx) => {
return (
<div
className={`img-container ${_settings.className}-img-container`}
key={pic.name+idx}
>
<img
src={pic.url}
alt={pic.name}
style={{background: '#fff'}}
onError={(e)=>{
const {target} = e;
if(target instanceof HTMLImageElement){
target.setAttribute('height', target.style.height);
target.setAttribute('visibility', target.style.visibility);
target.style.height = '0px';
target.style.visibility = 'none';
}
}}
onLoad={(e)=>{
const {target} = e;
if(target instanceof HTMLImageElement && target.dataSet){
const { height, visibility } = target.dataSet;
target.style.height = height ?? 'auto';
target.style.visibility = visibility ?? 'auto';
}
}}
/>
</div>
)
}
)}
</ISlider>
</div>
);
}
export default CustomCarousel;
调用组件
最后,在调用CustomCarousel
时,传入了经过处理的图片列表picList
,设置宽度和高度以及特定的settings
。其中,利用isRtlLayout()
函数来决定是否需要阿拉伯语支持,即settings.rtl
属性。
jsx
<CustomCarousel
picList={resortPicList(picInfoList).map(item=>({url:item.compressPicUrl}))}
width={window.innerWidth}
height={300}
settings={{
className: 'custom-carousel',
dots: true,
autoplay: true,
infinite: true,
speed: 1000,
slidesToShow: 1,
slidesToScroll: 1,
rtl: isRtlLayout(),
}}
/>
通过上述分析和解读,阐述了轮播图组件支持阿拉伯语使用习惯的必要自定义属性和行为逻辑。该组件在满足多样化布局和文化需求上表现出色,为全球化的用户界面设计提供了有价值的参考。