继上一篇随笔,优化3张以上图片轮播React组件
import React from 'react'; import PropTypes from 'prop-types'; import {getSwipeWay} from '../utils/swipe'; //imgs : 图片src数组 //playTime : 轮播下一张图片的时间间隔 //notAuto : 是否开启自动轮播 默认开启 false const PropsChecker = { imgs : PropTypes.array.isRequired, playTime : PropTypes.number, notAuto : PropTypes.bool, }; class Carousel extends React.Component { static defaultProps = { playTime : 5000, notAuto : false, } constructor(args){ super(args); this.state = { }; //缓存各个currIndex的ul之后的标签 this.storeElements = {}; //判断滑动手势 this.swipeWay = getSwipeWay(50);//闸值50 //图片显示的限制 this.limit = 3; //当前展示的图片 this.currIndex = 0; //展示的数组 this.showImgs = []; //手势滑动坐标 this.position = { x1:0, x2:0, y1:0, y2:0, }; //<ul> this.Ul = null; //禁止在transiton的期间操作 this.isTransition = false; //定时器 this.timer = 0; } componentDidMount(){ this.autoPlay(); } componentWillUnmount(){ clearTimeout(this.timer); } getHead(arr){ if(Array.isArray(arr)){ return arr[0]; } console.error('非数组'); } getLast(arr){ if(Array.isArray(arr)){ const len = arr.length; return arr[len-1]; } console.error('非数组'); } calcIndex(){ const {imgs} = this.props; const len = imgs.length; const limit = this.limit; const currIndex = this.currIndex; if(currIndex == 0){ this.showImgs = imgs.slice(0,limit - 1); this.showImgs.unshift(this.getLast(imgs)); return; } if(currIndex == len - 1){ this.showImgs = imgs.slice(len -2 ,len); this.showImgs.push(this.getHead(imgs)); return; } this.showImgs = imgs.slice(currIndex -1 , currIndex + limit -1); } changeCurrIndex(flag){ const {imgs} = this.props; const last = imgs.length -1; const currIndex = this.currIndex; if(flag === '-'){ this.currIndex = currIndex == 0 ? last : currIndex -1 ; return; } if(flag === '+'){ this.currIndex = currIndex == last ? 0 : currIndex + 1 ; return; } } ulTranslate(value){ const Ul = this.Ul; if(Ul){ if(Ul.style.webkitTranslate ){ Ul.style.webkitTranslate = value; }else{ Ul.style.translate = value; } } } createUl(){ const currIndex = this.currIndex; const storeElements = this.storeElements; //缓存这些标签,避免多次创建,很有必要 if(!storeElements[currIndex]){ //要保证<ul>key不同 也就是每次轮播后都要是新的标签,有损性能 const Ul = (<ul onTouchEnd={this.touchEnd} onTouchMove={this.touchMove} onTouchStart={this.touchStart} onTransitionEnd={this.transitionEnd} ref={(ele)=>this.Ul=ele} key={currIndex}> {this.createLis()} </ul>); storeElements[currIndex] = Ul; } return storeElements[currIndex]; } createLis(){ this.calcIndex(); const imgs = this.showImgs; return imgs.map((src,i)=>{ const liStyle = { // translate:(-i)+'00%', translate:( (i+'00') - 100 ) + '%', WebkitTranslate:( (i+'00') - 100 ) + '%', }; return <li className='item' key={i} style={liStyle} ><img src={src} /></li>; }); } touchStart = (e) => { if(this.isTransition){ return; } clearTimeout(this.timer); const {clientX,clientY} = e.touches[0]; this.position.x1 = clientX; this.position.y1 = clientY; } touchMove = (e) => { } touchEnd = (e) => { if(this.isTransition){ return; } const {clientX,clientY} = e.changedTouches[0]; this.position.x2 = clientX; this.position.y2 = clientY; const {x1,x2,y1,y2} = this.position; const direction = this.swipeWay(x1,x2,y1,y2); if( direction === 'Left'){ this.changeCurrIndex('+'); this.isTransition = true; this.ulTranslate('-100%'); } if(direction === 'Right'){ this.changeCurrIndex('-'); this.isTransition = true; this.ulTranslate('100%'); } } next(){ this.changeCurrIndex('+'); this.isTransition = true; this.ulTranslate('-100%'); } autoPlay(){ const {playTime,notAuto} = this.props; if(!notAuto){ this.timer = setTimeout(()=>{ this.next(); },playTime); } } transitionEnd = (e) => { this.forceUpdate(()=>{ this.isTransition = false; this.autoPlay(); }); } render(){ return (<div className='mm-carousel' > {this.createUl()} </div>); } } export default Carousel; Carousel.propTypes = PropsChecker;