大三学生的第二个基于 React 框架的轮播图组件。

3,203 阅读6分钟

在之前文章中介绍了使用原生 JS 实现轮播图插件的过程,大家可以点击这里去查看,本文介绍一下基于 React 框架的轮播图实现。

目前在找实习工作,有合适的机会希望小伙伴们多多推荐~

概要

本文主要讲述一个基于 React 的Slider 组件的开发过程,有些地方可能会比较啰嗦,大神可以忽略~

虽然是一个小小的轮播图组件,但是我还是希望将它作为一个完整的项目进行对待。

完整的开发过程如下:

  • 项目背景
  • 产品需求
  • 开发需求
  • 实现过程
  • 提交代码
  • 发布
  • 小结

项目背景

现代Web项目的开发使用的技术栈一般不会采用原生 JS 或者基于 Jquery 进行刀耕火种式的开发,而是使用 React 或者 Vue 框架。 由于我们是基于 React 框架实现该轮播组件,所以我们需要在 React 的规则之内进行开发。那么,至少我们需要熟悉 React 的使用以及组件开发过程。

React 的使用

React 是一个 MVVM 框架,拥有很多功能,但核心思想却很明确。

React 的核心是数据驱动视图以及组件化思想,所以我们最常用到的就是:

  • 通过 setState 改变状态,同时驱动视图更新。
  • 将父组件中的数据通过 props 传递给子组件,完成父子数据传递。
  • 将页面拆分成一个又一个的功能组件,然后将组件拼成一个个完整的模块,最终组装成一个页面。

使用 React 开发组件

使用 React 开发组件,那么少不了 Webpack,我们需要接入 Babel 转译 ES6 和 jsx 语法。

产品需求

产品需求和大三学生的第一个轮播图组件一样。

  • 能够实现自左向右的轮播。
  • 轮播到最后一张图时,能够无缝衔接到第一张图。
  • 点击图片能够跳转到对应链接。
  • 点击缩略圆点能够滚动到对应图片。

开发需求

开发需求也和大三学生的第一个轮播图组件一样。

  • 支持图片和点击链接的可配置。
  • 支持轮播持续时间的配置。
  • 支持轮播间隔时间的配置。
  • 支持轮播图显示容器的配置。
  • 支持缩略圆点的颜色、激活颜色、半径、距离底部位置的配置。

实现

  • 首先,在 github 上创建一个仓库react-slider
  • 将 github 创建好的仓库拉取到本地。
    git clone 【仓库地址】
    
  • 进入本地目录
    cd react-slider
    
  • 初始化 npm 仓库
    npm init
    
  • 编写 Webpack 配置 我们使用 html-webpack-plugin 打包 demo 页面,用 webpack-dev-server在本地启动一个服务器快速调试,同时支持 sassless 语法支持。

完整的 webpack.config.js 配置如下:

    const path = require("path");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    const htmlWebpackPlugin = new HtmlWebpackPlugin({
        template: path.join(__dirname, "demo/demo.html"),
        filename: "./index.html"
    });
    module.exports = {
        entry: path.join(__dirname, "demo/demo.js"),
        output: {
        path: path.join(__dirname, "./dist"),
        filename: "dist.js"
    },
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                use: "babel-loader",
                exclude: /node_modules/
            },
            {
                test: /\.css$/,
                use: ["style-loader", "css-loader"]
            },
            {
                test: /\.scss$/,
                use: ["style-loader", "css-loader", "sass-loader"]
            },
            {
                test: /\.less$/,
                use: ["style-loader", "css-loader", "less-loader"]
            }
        ]
    },
    plugins: [htmlWebpackPlugin],
    resolve: {
        extensions: [".js", ".jsx"]
    },
    devServer: {
        port: 3001
    }
};
  • 安装依赖 为了满足以上 webpack 配置的功能,我们需要安装一些依赖:
{
  "name": "react-slider-fjj",
  "version": "0.0.1",
  "description": "react-slider",
  "main": "./dist/slider.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack-dev-server --mode=development",
    "demo": "webpack --config ./webpack.config.js --progress --colors",
    "build": "babel slider -d dist --copy-files"
  },
  "author": "fengjiangjun",
  "license": "ISC",
  "devDependencies": {
    "babel": "^6.23.0",
    "babel-cli": "^6.26.0",
    "babel-core": "~6.26.0",
    "babel-loader": "^7.1.5",
    "babel-preset-env": "^1.7.0",
    "babel-preset-react": "^6.24.1",
    "css-loader": "^2.1.0",
    "html-webpack-plugin": "^3.2.0",
    "less": "^3.9.0",
    "less-loader": "^4.1.0",
    "source-list-map": "^2.0.1",
    "style-loader": "^0.23.1",
    "watchpack": "^1.6.0",
    "webpack": "^4.29.5",
    "webpack-cli": "^3.2.3",
    "webpack-dev-server": "^3.2.1"
  },
  "dependencies": {
    "react": "^16.8.3",
    "react-dom": "^16.8.3"
  }
}

注意,由于 npm 是国外服务器,安装过程可能会比较慢,为了提高安装速度,我们需要将 npm 源改成国内镜像,目前使用最广泛的就是淘宝镜像,我们改一下。

npm config set registry http://registry.npmjs.taobao.org

这样,在执行npm包的安装操作时,速度会大大提升。

执行安装命令

npm install
  • 做好了准备工作,接下来开始编码实现了。 轮播图的主要难点在于如何在图片轮播到最后一张时无缝切换到第一张,这个细节在上一篇大三学生的第一个轮播图组件中已经进行了讲解,所以本文就不再做详细描述啦,感兴趣的话,大家可以查看上一篇哈~

贴一下主要代码:

import React from 'react';
import './index.css';
export default class extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      index: 1
    }
    this.container = React.createRef();
    this.imgWrapper = React.createRef();
    this.list = this.props.list;
    //将图片数组的第一张图放到数组最后,通过此方法 hack 无缝轮播。
    this.list.push(this.props.list[0]);
  }
  componentDidMount () {
    if (!this.list) {
      return;
    }
    this.container.current.style.width = this.props.width + "px";
    this.container.current.style.height = this.props.height + "px";
    this.imgWrapper.current.style.height = this.props.height + "px";
    const count = this.list.length;
    this.imgWrapper.current.style.width = count * this.props.width + 'px';
    this.time = setTimeout(this.loop.bind(this), this.props.intervalTime || 2000);
    this.imgWrapper.current.addEventListener('transitionend', () => {
      this.time = setTimeout(this.loop.bind(this), this.props.intervalTime || 2000);
      if (this.state.index == count) {
        this.imgWrapper.current.style.transition = '0s';
        this.imgWrapper.current.style.transform = 'translateX(0px)';
        this.state.index = 1;
      }
    })
  }
  loop () {
    if (this.state.index < this.list.length) {
      this.imgWrapper.current.style.transition = this.props.transitionTime || '2s';
      this.imgWrapper.current.style.transform = 'translateX(' + (-this.state.index * this.props.width) + 'px)';
    }
    this.setState(prevState => ({
      index: prevState.index + 1
    }))
  }
  render () {
    return <div className='container' ref={this.container}><div className='img-wrapper' ref={this.imgWrapper}>
      {this.list.map(item => {
        return <img src={item.text} style={{ width: this.props.width }} className='img-item' onClick={() => { window.open(item.href); }} />

      })}
    </div>
      <div className="round-container">
        {this.list.map(
          (item, index) => {
            if (index == this.list.length - 1) {
              return null;
            }
            if (this.state.index - 1 === index && this.state.index !== (this.list.length)) {
              return <div className="yello"></div>
            }
            if (this.state.index == (this.list.length) && index == 0) {
              return <div className="yello"></div>
            }
            return <div className='red' onClick={() => { clearTimeout(this.time); this.setState({ index: index }); this.time = setTimeout(this.loop.bind(this), 0); }}>
            </div>
          })}
      </div>
    </div>
  }
}
  • 推送到 github

推送到 github ,比较简单了,只需几步简单的 git 命令即可。

// 保存本地修改
git add ./
// 提交本次修改
git commit -m ''
// 推送到远程服务器。
git push origin master

但是我们需要为我们的组件增加一个 demo 页面,所以我们最好能够将我们的 demo 页面提供给别人查看,这里我们依然采用 github 的功能。

1、首先新建一个分支 gh-pages,这个分支名字是固定的,不可换成其他的,否则产生不了我们的在线预览页面。

git checkout -b gh-pages

2、其次生成本地的demo页面。

npm run demo

将 gh-pages 分支内容推送到 github。

3、到 github 网站对应的仓库上,点击 Settings:

4、往下翻到 github pages 节点

看到的这个网址,就是该项目对应的 gh-pages 的根目录。

经过以上几个简单的命令,我们就能够将本地的 demo 页面推送到 github 服务器供别人预览了。

发布到 npm 仓库。

  • 首先,我们要有npm 账户,如果没有,请先去 npm 网站去注册。 假设 testuser 为你的 npm 账号。

首次发布命令如下:

npm adduser testuser
npm publish

如果之前成功执行过npm adduser,那么之后的发布命令仅仅使用 npm publish即可。

经过这两个简单的命令,我们就将组件发布到了npm 仓库中,此时,其他同学就可以通过npm 安装该组件进行使用了。

小结

作为一个准前端毕业生,在学习前端过程中势必会遇到点点滴滴的知识,这些知识点对于以后工作是很有帮助的,有一些是经常会打交道的,比如 git 常用命令,npm 常用命令,所以在此做个总结,希望能给未来的前端开拓者带来一些帮助。

以上就是 React 版本 Slider 的开发过程,希望能给大家带来帮助。