react中使用swiper

2,054 阅读7分钟
原文链接: www.oecom.cn

最近的react项目需要使用轮播图,自然而然的就想到了swiper,一直想通过npm安装的方式来使用,但是网上找了很多,资料很少,于是就暂时通过在index.html里直接引用swiper的js和css文件的方式来加载,下面来说一下具体的步骤和使用方法。

首先说一下我这里使用的是swiper3x系列。接下来说具体的步骤:

在index.html中引入js和css文件

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="theme-color" content="#000000">
   
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
      <link rel="stylesheet" type="text/css" href='%PUBLIC_URL%/static/css/swiper.min.css'>
  
    <title>React App</title>
  </head>
  <body>
    <div id="root"></div>
  
    <script src='%PUBLIC_URL%/static/js/swiper.min.js'></script>
  </body>
</html>

当然,我这个是将js和css文件下载到了本地,你也可以使用cdn路径,至此,引入基本上算是引入完成了,接下来就是如何在react组件中进行调用

在这里需要说一下,引入的js文件在组件当中不能直接使用,需要在最开始的位置声明一个变量,后续的使用方法和普通的html写法就一致了,区别就在于应该在哪个生命周期中写,个人建议实在componentDidUpdate周期中进行写,因为有时候数据是异步获取的,刚刚完成时不一定数据获取完成,数据获取完成以后更新state,此时会触发update周期。

import React,{Component} from 'react'
 
let Swiper = window.Swiper
class About extends Component{
	constructor(props){
		super(props);
		this.state = {
			myName : "这里是about页面",
			
		}
	}
	
componentWillUnmount() {
    if (this.swiper) { // 销毁swiper
      this.swiper.destroy()
    }
  }
componentDidUpdate(){
  if(this.swiper){
      this.swiper.slideTo(0, 0)
      this.swiper.destroy()
      this.swiper = null;
    }
	this.swiper = new Swiper(this.refs.lun, {
             loop:true,
             pagination: {
             el: '.swiper-pagination',
             clickable: true,
            },
          });
	}
render(){		
return (
   <div>
      <div className="swiper-container" ref="lun">
      <div className="swiper-wrapper">
      <div className="swiper-slide" data-id="0">Slide 1</div>
      <div className="swiper-slide" data-id="1">Slide 2</div>
      <div className="swiper-slide" data-id="2">Slide 3</div>
      <div className="swiper-slide" data-id="3">Slide 4</div>
      <div className="swiper-slide" data-id="4">Slide 5</div>
      <div className="swiper-slide" data-id="5">Slide 6</div>
      <div className="swiper-slide" data-id="6">Slide 7</div>
      <div className="swiper-slide" data-id="7">Slide 8</div>
      <div className="swiper-slide" data-id="8">Slide 9</div>
      <div className="swiper-slide" data-id="9">Slide 10</div>
    </div>
<div id="PgFather">
 <div className="swiper-pagination" id='body-left-pagination'></div>
</div>
   
  </div>
				
			</div>
		)
	}
}
export default About

如此便完成了一个轮播的实现,这里我写的demo只是将数据写死在了组件里,一般情况应该是通过异步来进行获取数据。

其实,这里还有一个问题,就在于给swiper-slide添加点击事件,一般来说是直接给swiper-slide这个div添加一个onClick事件,但是问题就出现在了这里,若这个轮播是可以循环轮播的话,swiper会自动生成两个节点,一个是第一个节点,一个是最后一个节点,分别放置于最后和最开始,便于轮播联动。然而他复制节点的时候,无法复制其onClick的点击事件,这就造成了当swiper初始化完成以后向左滑动第一个和向右滑动到最后一个再滑一次这两个节点是没有点击事件的。于是我们就应该使用到swiper的回调函数了,下面我们对构建swiper的方法进行改造一下。

this.swiper = new Swiper(this.refs.lun, {
             loop:true,
             pagination: {
             el: '.swiper-pagination',
             clickable: true,
             onClick: function(swiper,e){
 
            var paginationContainer= document.getElementById('PgFather');
            var paginationFather = document.getElementById('body-left-pagination');
//这里是判断是否点击的轮播底部圆点,因为方法在点击圆点的时候也会触发,所以为了能保证点击圆点轮播效果,应该将其屏蔽掉
            if(!this.isDOMContains(paginationFather,e.target,paginationContainer)){
              var se = document.querySelectorAll(".body-left-lunbo .swiper-slide");
              var nowNode = "";
              var index = swiper.activeIndex;
 
              if(index==0){
                index =  se.length-3;
              }else if(index==se.length-1){
                index=0;
              }else{
                index = swiper.activeIndex-1;
              }
 
 
              if(self.state.swiperList.length===1){
                nowNode = se[0];
              }else{
                for(var i=0;i<se.length;i++){
                  if(se[i].getAttribute('data-swiper-slide-index')==index){
                    nowNode = se[i]
                  }
                }
              }
              if(nowNode){
                var id= nowNode.getAttribute("data-id");
                var itemObj = {
                  id:id
                }
                goDetail(itemObj,self.state.myName)
                return true
              }
            }else{
              return false
            }
        }
            },
          });

通过上面方法就可以实现了swiper的点击事件。我上面的代码中补充了一种条件就是当swiper轮播节点只有一个的时候回出现点击无效的情况,针对这一情况在方法里进行判断一下,如果只有一个节点直接将节点0赋值给nowNode即可。

上面有一个判断是否点击的是底部圆的点判断我在下面贴出来供大家参考

isDOMContains:function(parentEle,ele,container){
    console.log(parentEle)
    //判断一个节点是否是其子节点
  //parentEle: 要判断节点的父级节点
  //ele:要判断的子节点
  //container : 二者的父级节点
 
  //如果parentEle h和ele传的值一样,那么两个节点相同
  if(parentEle == ele){
    return true
  }
  if(!ele || !ele.nodeType || ele.nodeType != 1){
    return false;
  }
  //如果浏览器支持contains
  if(parentEle.contains){
    return parentEle.contains(ele)
  }
  //火狐支持
  if(parentEle.compareDocumentPosition){
    return !!(parentEle.compareDocumentPosition(ele)&16);
  }
 
  //获取ele的父节点
  var parEle = ele.parentNode;
  while(parEle && parEle != container){
    if(parEle == parentEle){
      return true;
    }
    parEle = parEle.parentNode;
  }
  return false;
}