react中创建一个轮播器组件

创建轮播器组件

需要解决的问题:

  • 确保传入的props参数格式的正确性
  • 在React中操作React创建的DOM元素
  • 组件状态切换时,对于setInterval函数的操作,以确保不会报错

问题解决
props参数使用prop-types包设置参数格式以及默认props的设置,确保props的正确性

使用react提供的ref属性来操作react创建的dom元素属性

在不同的钩子函数中调用生成setInterval和清除setInterval函数

componentDidMount() {
   this.scoll();	// 执行核心函数,运行轮播器,在其内部将setInterval赋值给this.timer
}

// 解决组件状态改变setInterval函数报错问题 
componentWillReceiceProps(){
    clearInterval(this.timer); //清除之前的轮播函数中的定时器
    setTimeout(()=>{
       this.scroll();   // 重新执行轮播函数 
    },0);
}

这种方法虽然可以实现效果,但当组件被销毁重建时会报错。改进方法如下:

componentWillReceiveProps(){
    if(this.timer !== undefined){
        setTimeout(() => {
            clearInterval(this.timer); // 卸载定时函数
            this.scoll();
        },0);
    }else{
        this.scoll();
    }   
}			

实际代码如下

import React, {Component} from 'react';
import {Link} from 'react-router-dom';
import PropTypes from 'proptypes';
import Style from './Banner.module.css';

const defaultProps = {
    lists: []
};

class Banner extends Component{
    scoll = () => {
        var i = 0;
        var j = 0;
        var num = this.props.lists.length;
        if(num > 1){
            this.refs.banner.style.width = (num+1)*100+'vw';
            let btns = document.getElementById('bannerBtn')
                .querySelectorAll('li');
            this.timer = setInterval(function () {
                if(i>num){
                    this.refs.banner.style.transition = 'all 0s ease';
                    i=0;
                }else{
                    this.refs.banner.style.transition = 'all 1s ease';
                }
                this.refs.banner.style.left = -i*100+'vw';
                if((j > num-1) || (i === num) || (i===0)){
                    j=0;
                }
                btns.forEach((btn,index)=>{
                    if(index === j){
                        btn.style.background = '#fafafa';
                    }else{
                        btn.style.background = 'transparent';
                    }
                });
                i++;
                j++;
            }.bind(this),2000);
        }
    };

    componentDidMount() {
        // 组件渲染完执行
        this.scoll();
    }

    componentWillReceiveProps() {
        // props发生改变时执行
        if(this.timer !== undefined){
            setTimeout(() => {
                clearInterval(this.timer); // 卸载定时函数
                this.scoll();
            },0);
        }else{
            this.scoll();
        }
    }

    componentWillUnmount() {
        // 组件被卸载或销毁时执行
        clearInterval(this.timer); // 卸载定时函数
    }

    render() {
        var imgs = this.props.lists.map((list,index)=>{
            return (
	            <Link to={list.url} key={index}>
	            	<img src={list.img} alt=''/>
	            </Link>
	        );
        });
        var first = this.props.lists.length > 1 ?
            <Link to={this.props.lists[0].url}>
                <img src={this.props.lists[0].img} alt='' />
            </Link>
            :'';
        var btns = this.props.lists.map((list,index)=>{
            if(index===0){
                return <li style={{background: '#fafafa'}} key={index}></li>;
            }else{
                return <li key={index}></li>;
            }
        });

        return (
            <div className={Style.banner} onClick={this.scroll}>
                <div className={Style.bannerMain} ref="banner">
                    {imgs}
                    {first}
                </div>
                <div className={Style.btn}>
                    <ul id='bannerBtn'>
                        {btns}
                    </ul>
                </div>
            </div>
        );
    }
}

Banner.defaultProps = defaultProps;
Banner.propTypes = {
    lists: PropTypes.array
};

export default Banner;

不喜勿喷

猜你喜欢

转载自blog.csdn.net/wang19970228/article/details/95220352
今日推荐