React实现轮播组件的开发例子

第一步,需求

首先,写一个组件必须先考虑改组件的需求有哪些,支持的配置需要哪些。
如上已经说了改组件的需求:

轮播的图片
配置轮播图片切换的速度
可配置是否自动轮播
可配置自动轮播的时候鼠标放上去是否暂停
可配置自动轮播的速度
可配置是否需要前后箭头
可配置是否需要 dot (我不知道怎么表述好,反正意思你懂)
这一步先到此为止~~~
第二步,构建项目

这里我们是使用 React 框架,当然也是用它的好搭档 webpack 来构建自动化流程咯~?
不懂 webpack 的配置可以看我的博客关于 webpack 使用的文章,谢谢~?
这是项目开发目录的文件结构:

src
├── Slider              #Slider组件
|   |
|   ├──SliderItem         
|   |   ├──SliderItem.jsx
|   |   └──SliderItem.scss
|   |
|   ├──SliderDots       
|   |   ├──SliderItem.jsx
|   |   └──SliderItem.scss
|   |
|   ├──SliderArrows        
|   |   ├──SliderItem.jsx
|   |   └──SliderItem.scss
|   |
|   ├──Slider.jsx        
|   |
|   └──Slider.scss
|
├──images              #存放demo用的图片文件
|
└── index.js           #demo的入口文件
看目录结构我们应该明白了,我们主要关注 Slider 文件夹。

第三步,基于需求的开发

这里我们开发组件的模式是按照需求驱动型,回到第一步的需求,我们先不管组件内代码,先写出我们想怎么样配置使用组件:

// index.js
import React from 'react';
import { render } from 'react-dom';
import Slider from './Slider/Slider';

const IMAGE_DATA = [
  {
    src: require('./images/demo1.jpg'),
    alt: 'images-1',
  },
  {
    src: require('./images/demo2.jpg'),
    alt: 'images-2',
  },
  {
    src: require('./images/demo3.jpg'),
    alt: 'images-3',
  },
];

render(
  <Slider
    items={IMAGE_DATA}
    speed={1.2}
    delay={2.1}
    pause={true}
    autoplay={true}
    dots={true}
    arrows={true}
  />,
  document.getElementById('root')
);
可以看到,在使用 Slider 组件的时候,根据需求,我们可以传入这些属性来配置组件。
一个 items 数组,决定了需要轮播的内容,items 里面每个元素都是一个对象,有 src 和 alt 属性,分别是轮播图片的 src 地址和 alt 内容;
speed 是图片切换的时候的速度时间,需要配置一个 number 类型的数据,决定时间是几秒;
autoplay 是配置是否需要自动轮播,是一个布尔值;
delay 是在需要自动轮播的时候,每张图片停留的时间,一个 number 值;
pause 是在需要自动轮播的时候,鼠标停留在图片上,是否暂停轮播,是一个布尔值;
dots 是配置是否需要轮播下面的小点;
arrows 是配置是否需要轮播的前后箭头;

第四步,编写组件

首先我们来考虑一下需要多少个组件,最外层的 Slider 组件是毋庸置疑的了。
根据需求我们可以分出一个 SliderItem 组件,一个 SliderDots,一个 SliderArrows 组件,分别是 轮播每个图片的item,轮播下面dots的组件,左右箭头组件。
我们先来编写每个小组件,组件是对外封闭独立的,所以它只需要对外暴漏属性的配置即可。

SliderItem

因为 SliderItem 是展示轮播图片的每个内容的,所以它需要的属性有,src 和 alt,因为之前我们已经把每个轮播项写成一个对象了,所以把 src 和 alt 作为属性放在 item,我们只需要一个 item 属性即可;它还需要决定它在父组件中大小,因为在未使用组件的时候我们是不知道轮播项的数目的,所以它的宽度需要根据父组件传给它count(图片数目)来计算。
所以它需要的属性有:

item (有 src 和 alt 属性)
count (轮播项总数目,计算每个轮播项的宽度)
import React, { Component } from 'react';

export default class SliderItem extends Component {
  constructor(props) {
    super(props);
  }

  render() {
    let { count, item } = this.props;
    let width = 100 / count + '%';
    return (
      <li className="slider-item" style={{width: width}}>
        <img src={item.src} alt={item.alt} />
      </li>
    );
  }
}
let width = 100 / count + '%'; 即是计算它占父组件的宽度百分比。

SliderDots

对于 SliderDots 组件,我们需要一个 count(轮播项总数目)来决定显示几个 dot,还需要一个 nowLocal 属性来判断哪个 dot 对应当前显示的轮播项,点击每个 dot 的是否需要一个回调函数 turn 来做出响应。
所以它需要的属性有:

count(轮播项总数目)
nowLocal(当前的轮播项)
turn(点击 dot 回调函数)
import React, { Component } from 'react';

export default class SliderDots extends Component {
  constructor(props) {
    super(props);
  }

  handleDotClick(i) {
    var option = i - this.props.nowLocal;
    this.props.turn(option);
  }

  render() {
    let dotNodes = [];
    let { count, nowLocal } = this.props;
    for(let i = 0; i < count; i++) {
      dotNodes[i] = (
        <span
          key={'dot' + i}
          className={"slider-dot" + (i === this.props.nowLocal?" slider-dot-selected":"")}
          onClick={this.handleDotClick.bind(this, i)}>
        </span>
      );
    }
    return (
      <div className="slider-dots-wrap">
        {dotNodes}
      </div>
    );
  }
}
代码可以看出,我们用 for 循环根据 count 来决定了需要多少个 dot,然后在每个 dot 绑定函数传入一个 i 值,并且如果这个 dot 对于当前显示的轮播项,就多加一个class slider-dot-selected。
每个 dot click 绑定的函数还需要计算需要向前或者向后移动多少个轮播项,然后回调 turn 函数。

SliderArrows

对于 SliderArrows 组件,我们只需要一个 turn 函数作出回调。
废话不多少,代码如下:

import React, { Component } from 'react';

export default class SliderArrows extends Component {
  constructor(props) {
    super(props);
  }

  handleArrowClick(option) {
    this.props.turn(option);
  }

  render() {
    return (
      <div className="slider-arrows-wrap">
        <span
          className="slider-arrow slider-arrow-left"
          onClick={this.handleArrowClick.bind(this, -1)}>
          &lt;
        </span>
        <span
          className="slider-arrow slider-arrow-right"
          onClick={this.handleArrowClick.bind(this, 1)}>
          &gt;
        </span>
      </div>
    );
  }
}
这个组件下面有两个箭头,分别是向前和向后,回调的 turn 是 1 和 -1。

Slider 组件

import React, { Component } from 'react';

require('./Slider.scss');

import SliderItem from './SliderItem/SliderItem';
import SliderDots from './SliderDots/SliderDots';
import SliderArrows from './SliderArrows/SliderArrows';

export default class Slider extends Component {
  constructor(props) {
    super(props);
    this.state = {
      nowLocal: 0,
    };
  }

  // 向前向后多少
  turn(n) {
    var _n = this.state.nowLocal + n;
    if(_n < 0) {
      _n = _n + this.props.items.length;
    }
    if(_n >= this.props.items.length) {
      _n = _n - this.props.items.length;
    }
    this.setState({nowLocal: _n});
  }

  // 开始自动轮播
  goPlay() {
    if(this.props.autoplay) {
      this.autoPlayFlag = setInterval(() => {
        this.turn(1);
      }, this.props.delay * 1000);
    }
  }

  // 暂停自动轮播
  pausePlay() {
    clearInterval(this.autoPlayFlag);
  }

  componentDidMount() {
    this.goPlay();
  }

  render() {
    let count = this.props.items.length;

    let itemNodes = this.props.items.map((item, idx) => {
      return <SliderItem item={item} count={count} key={'item' + idx} />;
    });

    let arrowsNode = <SliderArrows turn={this.turn.bind(this)}/>;

    let dotsNode = <SliderDots turn={this.turn.bind(this)} count={count} nowLocal={this.state.nowLocal} />;

    return (
      <div
        className="slider"
        onMouseOver={this.props.pause?this.pausePlay.bind(this):null} onMouseOut={this.props.pause?this.goPlay.bind(this):null}>
          <ul style={{
              left: -100 * this.state.nowLocal + "%",
              transitionDuration: this.props.speed + "s",
              width: this.props.items.length * 100 + "%"
            }}>
              {itemNodes}
          </ul>
          {this.props.arrows?arrowsNode:null}
          {this.props.dots?dotsNode:null}
        </div>
      );
  }
}

Slider.defaultProps = {
  speed: 1,
  delay: 2,
  pause: true,
  autoplay: true,
  dots: true,
  arrows: true,
  items: [],
};
Slider.autoPlayFlag = null;
在这里我们先是 import 依赖,以及 需要的 子组件。
Slider 有一个状态 nowLocal,是表明当前轮播的第几项。
前面一直讲 turn 函数,我们就先分析一下这个函数:
turn(n) {
  console.log();
  var _n = this.state.nowLocal + n;
  if(_n < 0) {
    _n = _n + this.props.items.length;
  }
  if(_n >= this.props.items.length) {
    _n = _n - this.props.items.length;
  }
  this.setState({nowLocal: _n});
}
它传入一个 参数 n ,决定向前或者向后移动多少个轮播项,向前和向后分别对于 - 和 +。
turn 函数内,声明一个 _n 变量表示下一个轮播的第几项。
如果 _n 小于 0 ,那当然是不行的,所以就会让 _n 变成最后一项;
如果 _n 大于 items 的长度 ,那当然也是不行的,所以就会让 _n 变成第一项;
最后改变状态 nowLocal 等于 _n。

下面是一个开始自动轮播的函数 goPlay:
goPlay() {
  if(this.props.autoplay) {
    this.autoPlayFlag = setInterval(() => {
      this.turn(1);
    }, this.props.delay * 1000);
  }
}
如果 autoplay 是 true,则执行 setInterval 来自动调用 this.turn(1) 向前移动轮播项,this.props.delay * 1000就是根据配置的 delay 来决定多久移动一次。
这里我们需要一个 autoPlayFlag 参数来保存 setInterval 的回调,用来在鼠标停放在图片上停止自动轮播,我们把这个 autoPlayFlag 作为组件的一个属性来保存。

Slider.autoPlayFlag = null;
然后在组件初始化 componentDidMount 的时候调用这个函数:

componentDidMount() {
  this.goPlay();
}
我们还需要一个 pausePlay 函数来暂停自动轮播。

pausePlay() {
  clearInterval(this.autoPlayFlag);
}
最后就是 render 了,根据属性配置哪些函数和组件需要~

默认属性,这个是需要的,在使用属性的时候如果忘了一些配置项也不会出错。
Slider.defaultProps = {
  speed: 1,
  delay: 2,
  pause: true,
  autoplay: true,
  dots: true,
  arrows: true,
  items: [],
};
样式

什么,你告诉我显示在页面上的都是什么鬼?
来写 scss 吧:

* {
  margin: 0;
  padding: 0;
}
.slider {
  overflow: hidden;
  width: 100%;
  position: relative;

  &>ul {
    height: auto;
    overflow: hidden;
    position: relative;
    left: 0;
    transition: left 1s;
  }

  .slider-item {
    display: inline-block;
    height: auto;

    &>img {
      display: block;
      height: auto;
      width: 100%;
    }
  }

  .slider-arrow {
    display: inline-block;
    color: #fff;
    font-size: 50px;
    position: absolute;
    top: 50%;
    margin-top: -50px;
    z-index: 100;
    padding: 20px;
    cursor: pointer;
    font-weight: bold;

    &:hover {
      background: rgba(0,0,0,.2);
    }

    &.slider-arrow-right {
      right: 0;
    }
    &.slider-arrow-left {
      left: 0;
    }
  }

  .slider-dots-wrap {
    z-index: 99;
    text-align: center;
    width: 100%;
    position: absolute;
    bottom: 0;

    .slider-dot {
      display: inline-block;
      width: 6px;
      height: 6px;
      border: 3px solid #ccc;
      margin: 6px;
      cursor: pointer;
      border-radius: 20px;

      &:hover {
        border: 3px solid #868686;
      }

      &.slider-dot-selected {
        background: #ccc;
      }
    }
  }
}
这里不多说了,样式就这样~

时间: 2024-10-07 00:29:41

React实现轮播组件的开发例子的相关文章

使用React实现轮播效果组件示例代码_javascript技巧

前言 我发现React和AngularJS思想完全不同,AngularJS是基于双向绑定,在Modal层中定制数据,然后双向改变.但是React是通过prop和state来改变view层的状态.下面是我写的一个轮播图组件,可以直接看一下.代码很简单.原理就是通过React在componentDidMount后改变setState,来动态改变css样式. 说明以下:看gif很卡,但是实际效果还是很好的. 以下是示例代码 LunBo.js require('styles/App.css'); req

Bootstrap实现带暂停功能的轮播组件(推荐)_javascript技巧

最近博主在项目中用到一款轮播组件,功能齐全,可以设置各种标题样式.动画效果.轮播时间.开始暂停等功能,在此推荐给大家,供大家参考. 一.效果展示 多说无益,来看一组效果展示图,感受一下! 1.先跟大家见个面,打个招呼 2.什么?切换太慢了?好,加快速度! 3.加入其他功能 4.图片太小,看不出效果?好,那来个大图感受下! 5.如果你不想要右上角的小图标,照样可以. 6.如果你对上述滑动效果不满意,组件提供了其他几种图片切换方式 淡入淡出 水平滑动 7.再来一张图片定位 二.组件介绍 Orbit是

JavaScript实现图片轮播组件代码示例_javascript技巧

本文介绍了JavaScript实现图片轮播组件,废话不多说了直接看下面: 效果: 自动循环播放图片,下方有按钮可以切换到对应图片. 添加一个动画来实现图片切换. 鼠标停在图片上时,轮播停止,出现左右两个箭头,点击可以切换图片. 鼠标移开图片区域时,从当前位置继续轮播. 提供一个接口,可以设置轮播方向,是否循环,间隔时间. 对HTML.CSS的要求: <div class="carousel-box"> <div class="carousel"&g

值得分享的JavaScript实现图片轮播组件_javascript技巧

本文实例为大家分享了JavaScript实现图片轮播组件的使用方法,供大家参考,具体内容如下 效果: 自动循环播放图片,下方有按钮可以切换到对应图片. 添加一个动画来实现图片切换. 鼠标停在图片上时,轮播停止,出现左右两个箭头,点击可以切换图片. 鼠标移开图片区域时,从当前位置继续轮播. 提供一个接口,可以设置轮播方向,是否循环,间隔时间. 点击查看demo 对HTML.CSS的要求: <div class="carousel-box"> <div class=&qu

Bootstrap图片轮播组件Carousel使用方法详解_javascript技巧

Bootstrap是Twitter推出的一个开源的用于前端开发的工具包.它由Twitter的设计师Mark Otto和Jacob Thornton合作开发,是一个CSS/HTML框架.Bootstrap提供了优雅的HTML和CSS规范,它即是由动态CSS语言Less写成.Bootstrap一经推出后颇受欢迎,一直是GitHub上的热门开源项目,包括NASA的MSNBC(微软全国广播公司)的Breaking News都使用了该项目. 图片轮播组件是一个在网页中很常见的技术,但是如果直接编写的话,需

Bootstrap图片轮播组件使用实例解析_javascript技巧

使用Bootstrap来编写图片轮播组件Carousel,则能够节约很多时间,图片轮播组件是一个在网页中很常见的技术,但是如果直接编写的话,需要很长的JavaScript编码,同时也不好控制大小.  同时说一下,Carousel这个词的本义是回旋木马.  一.基本目标在网页编写多张图片的轮播组件Carousel,鼠标放在上面自带悬停效果,并且在每张图片下面配有图片说明.  由于笔者的电脑视频录制软件比较渣,也觉得没必要画太多时间在这上面,觉得只要能说明问题就行,所以下面的GIF失色比较严重,但是

12款经典的白富美型—jquery图片轮播插件—前端开发必备_jquery

图片轮播是网站中的常用功能,用于在有限的网页空间内展示一组产品图片或者照片,同时还有非常吸引人的动画效果.本文向大家推荐12款实用的 jQuery 图片轮播效果插件,帮助你在你的项目中加入一些效果精美的图片轮播效果,希望这些插件能够帮助到你. Nivo Slider 首先推荐的这款插件号称世界上最棒的图片轮播插件,有独立的 jQuery 插件和 WordPress 插件两个版本. 目前下载量已经突破 1,800,000 次!jQuery 独立版本的插件主要有如下特色: ✓  16个独特的过渡效果

LARAVEL 中使用 VUE 组件化开发例子

现今前端组件化开发.MVVM 模式,给开发带来了很多的便利,可读性.可维护性更高.然而自 Laravel 5.3 开始,VueJS 成为框架默认的标配. 本文基于 Laravel 5.1 LTS 版本引入 Vue 2.0 进行配置. 我已在 Github 配置好,Clone 下来后按照 README 安装依赖后即可用: https://github.com/jcc/vue-laravel-example 步骤一:配置 PACKAGE.JSON 1. 在根目录下修改 package.json, 可

jQuery图片轮播插件——前端开发必看_jquery

还记得以前刚接触前端的时候,浏览各大网站,很多都少不了的有个轮播的效果,那个时候自己是一个彻彻底底的小白,想着这些图片滚动起来还真是有意思,是什么让这些图片在一个方向上连续的滚动呢.后来慢慢的接触多了,觉得这些也是so easy的嘛,于是为了加深对js.jQuery的理解以及探究网站上各种效果的实现方法,就有了jQuery插件之路这样一个系列,当然为了纪念当初对轮播的执念,于是就从轮播开始写了一个小小的插件,这只是一个开始,随着后面的了解的更多,也会写一些更加绚丽的DEMO.有兴趣的朋友可以去看