jQuery图片轮播(二)利用构造函数和原型创建对象以实现继承


Posted in Javascript onDecember 06, 2016

上一篇文中完成的封装,还存在一个小问题,就是该轮播对象不能在同一页面中重复使用,本文将通过组合使用javascript的构造函数和原型模式创建对象来解决这个问题。

没有看过上一篇文章的朋友可以点此查看上一篇文章 (jQuery图片轮播实现并封装(一))

首先回顾一下,上文的问题所在,上文中的carsouel对象是采用字面量的方式来定义的,这样carsouel本就是一个实例,想要使用在多处时,这个对象的方法会发生冲突,最终只会执行最后的那一个。而通过采用构造函数的方式来定义对象carsouel,每次需要使用时只需要用new操作符来实例化一个新对象,页面中需要几处轮播就实例化几个对象,这样就可以满足需求。所以,将代码改成以下形式。

function Carousel(){
  this.now = 0;          //当前显示的图片索引
  this.hasStarted = false;     //是否开始轮播
  this.interval = null;      //定时器
  this.liItems = null;       //要轮播的li元素集合
  this.len = 0;         //liItems的长度
  this.aBox : null;        //包含指示器的dom对象
  this.bBox : null;        //包含前后按钮的dom对象
  /**
   * 初始化及控制函数
   * @param bannnerBox string 包含整个轮播图盒子的id或class
   * @param aBox string 包含指示器的盒子的id或class
   * @param btnBox string 包含前后按钮的盒子的id或class
   */
  this.startPlay = function(bannnerBox,aBox,btnBox) {
    //初始化对象参数
    var that = this;
    this.liItems = $(bannnerBox).find('ul').find('li');
    this.len = this.liItems.length;
    this.aBox = $(bannnerBox).find(aBox);
    this.bBox = $(bannnerBox).find(btnBox);
    //让第一张图片显示,根据轮播图数量动态创建指示器,并让第一个指示器处于激活状态,隐藏前后按钮
    this.liItems.first('li').css({'opacity': 1, 'z-index': 1}).siblings('li').css({'opacity': 0, 'z-index': 0});
    var aDom = '';
    for (var i = 0; i < this.len; i++){
      aDom += '<a></a>';
    }
    $(aDom).appendTo(this.aBox);
    this.aBox.find('a:first').addClass("indicator-active");
    this.bBox.hide();
    //鼠标移入banner图时,停止轮播并显示前后按钮,移出时开始轮播并隐藏前后按钮
    $(bannnerBox).hover(function (){
      that.stop();
      that.bBox.fadeIn(200);
    }, function (){
      that.start();
      that.bBox.fadeOut(200);
    });
    //鼠标移入指示器时,显示对应图片,移出时继续播放
    this.aBox.find('a').hover(function (){
      that.stop();
      var out = that.aBox.find('a').filter('.indicator-active').index();
      that.now = $(this).index();
      if(out!=that.now) {
        that.play(out, that.now)
      }
    }, function (){
      that.start();
    });
    //点击左右按钮时显示上一张或下一张
    $(btnBox).find('a:first').click(function(){that.next()});
    $(btnBox).find('a:last').click(function(){that.prev()});
    //开始轮播
    this.start()
  };
  //前一张函数
  this.prev = function (){
    var out = this.now;
    this.now = (--this.now + this.len) % this.len;
    this.play(out, this.now);
  };
  //后一张函数
  this.next = function (){
    var out = this.now;
    this.now = ++this.now % this.len;
    this.play(out, this.now);
  };
  /**
   * 播放函数
   * @param out number 要消失的图片的索引值
   * @param now number 接下来要轮播的图的索引值
   */
  this.play = function (out, now){
    this.liItems.eq(out).stop().animate({opacity:0,'z-index':0},500).end().eq(now).stop().animate({opacity:1,'z-index':1},500);
    this.aBox.find('a').removeClass('imgnum-active').eq(now).addClass('indicator-active');
  };
  //开始函数
  this.start = function(){
    if(!this.hasStarted) {
      this.hasStarted = true;
      var that = this;
      this.interval = setInterval(function(){
        that.next();
      },2000);
    }
  };
  //停止函数
  this.stop = function (){
    clearInterval(this.interval);
    this.hasStarted = false;
  }
};

调用时采用new操作符,如下:

var banner1 = new Carousel();
  var banner2 = new Carousel();
  var banner3 = new carousel();
  banner1.startPlay('#J_bg_ban1','#J_bg_indicator1','#J_bg_btn1');
  banner2.startPlay('#J_bg_ban2','#J_sm_indicator2','#J_bg_btn2');
  banner3.startPlay('#J_bg_ban3','#J_sm_indicator3','#J_bg_btn3');

上述方法可实现需求,但是仔细分析发现,这与上一篇文中使用extend复制对象的方法几乎是一样的,这里的new操作符实际上也是将构造函数完全复制了一份出来作为一个新的对象,那就和上文中提到的方法存在共同的缺点,那就是内部函数不能复用,每次执行用new操作符来实例化,都会创建新的内部函数,这也是单独使用构造函数来自定义对象的缺点。

在Carousel对象内的next函数,prev函数,strat函数,stop函数其实都是可以共用的,多个轮播件共用这些函数是完全没有问题的,而初始化函数和play函数需要作为私有函数来调用。单独使用构造函数创建的对象,当使用new操作符创建新实例的时候,初始化方法和play方法会被重新在每个实例上创建一遍,这正是我们想要的结果,而next方法、prev方法、start方法、stop方法这些可共用的方法也会被重新创建,而创造多个完成一样任务的方法是完全没有必要的,所以需要将这些共有的方法提出来,让所有Carousel对象的实例都可以公用,这样就可以解决函数复用的问题。

通过将这些共用的方法写在Carousel的原型对象上,在创建Carousel新实例的时候就可以通过原型链来共享这些方法,这样这些公用函数也就得到了复用,代码如下:

function Carousel(){
  this.now = 0;          //当前显示的图片索引
  this.hasStarted= false;     //是否开始轮播
  this.interval = null;      //定时器
  this.liItems = null;       //要轮播的li元素集合
  this.len = 0;          //liItems的长度
  this.aBox = null;        //包含指示器的dom对象
  this.bBox = null;        //包含前后按钮的dom对象
  /**
   * 初始化及控制函数
   * @param bannnerBox string 包含整个轮播图盒子的id或class
   * @param aBox string 包含指示器的盒子的id或class
   * @param btnBox string 包含前后按钮的盒子的id或class
   */
  this.startPlay = function(bannnerBox,aBox,btnBox) {
    //初始化对象参数
    var that = this;
    this.liItems = $(bannnerBox).find('ul').find('li');
    this.len = this.liItems.length;
    this.aBox = $(bannnerBox).find(aBox);
    this.bBox = $(bannnerBox).find(btnBox);
    //让第一张图片显示,根据轮播图数量动态创建指示器,并让第一个指示器处于激活状态,隐藏前后按钮
    this.liItems.first('li').css({'opacity': 1, 'z-index': 1}).siblings('li').css({'opacity': 0, 'z-index': 0});
    var aDom = '';
    for (var i = 0; i < this.len; i++){
      aDom += '<a></a>';
    }
    $(aDom).appendTo(this.aBox);
    this.aBox.find('a:first').addClass("imgnum-active");
    this.bBox.hide();
    //鼠标移入banner图时,停止轮播并显示前后按钮,移出时开始轮播并隐藏前后按钮
    $(bannnerBox).hover(function (){
      that.stop();
      that.bBox.fadeIn(200);
    }, function (){
      that.start();
      that.bBox.fadeOut(200);
    });
    //鼠标移入指示器时,显示对应图片,移出时继续播放
    this.aBox.find('a').hover(function (){
      that.stop();
      var out = that.aBox.find('a').filter('.indicator-active').index();
      that.now = $(this).index();
      if(out!=that.now) {
        that.play(out,that.now)
      }
    }, function (){
      that.start();
    });
    //点击左右按钮时显示上一张或下一张
    $(btnBox).find('a:first').click(function(){that.next()});
    $(btnBox).find('a:last').click(function(){that.prev()});
    //开始轮播
    this.start()
  };
  /**
   * 播放函数
   * @param out number 要消失的图片的索引值
   * @param now number 接下来要轮播的图的索引值
   */
  this.play = function (out,now){
    this.liItems.eq(out).stop().animate({opacity:0,'z-index':0},500).end().eq(now).stop().animate({opacity:1,'z-index':1},500);
    this.aBox.find('a').removeClass('imgnum-active').eq(now).addClass('indicator-active');
  };
}
Carousel.prototype = {
  //前一张函数
  prev : function (){
    var out = this.now;
    this.now = (--this.now + this.len) % this.len;
    this.play(out,this.now)
  },
  //后一张函数
  next : function (){
    var out = this.now;
    this.now = ++this.now % this.len;
    this.play(out,this.now);
  },
  //开始函数
  start : function(){
    if(!this.hasStarted) {
      this.hasStarted = true;
      var that = this;
      this.interval = setInterval(function(){
        that.next();
      },2000);
    }
  },
  //停止函数
  stop : function (){
    clearInterval(this.interval);
    this.hasStarted = false;
  }
};

在这里用字面量重写了Carousel对象的原型对象,将next方法,perv方法,start方法和stop方法写进了Carousel的原型对象中,这样每次实例化的对象就可以共用这些方法。当然,实例化的方法也是使用new操作符。

这种组合使用构造函数和原型的模式,是创建自定义类型最常用的方法,至此我们就完成了这个简单轮播对象的封装。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
xml和web特殊字符
Apr 28 Javascript
前端开发部分总结[兼容性、DOM操作、跨域等](持续更新)
Mar 04 Javascript
Javascript中的isNaN函数使用说明
Nov 10 Javascript
JS操作Cookie写入和读取实例代码
Oct 20 Javascript
页面定时刷新(1秒刷新一次)
Nov 22 Javascript
JavaScript改变CSS样式的方法汇总
May 07 Javascript
浅谈JS中的三种字符串连接方式及其性能比较
Sep 02 Javascript
vue利用better-scroll实现轮播图与页面滚动详解
Oct 20 Javascript
element-ui的回调函数Events的用法详解
Oct 16 Javascript
three.js实现炫酷的全景3D重力感应
Dec 30 Javascript
Nuxt使用Vuex的方法示例
Sep 06 Javascript
解决vue中的无限循环问题
Jul 27 Javascript
jQuery File Upload文件上传插件使用详解
Dec 06 #Javascript
vue2.0开发实践总结之入门篇
Dec 06 #Javascript
微信小程序中单位rpx和rem的使用
Dec 06 #Javascript
JavaScript定时器实现的原理分析
Dec 06 #Javascript
原生js实现弹出层登录拖拽功能
Dec 05 #Javascript
详解Vue.js——60分钟组件快速入门(上篇)
Dec 05 #Javascript
原生js编写基于面向对象的分页组件
Dec 05 #Javascript
You might like
php中iconv函数使用方法
2008/05/24 PHP
YII2框架中使用yii.js实现的post请求
2017/04/09 PHP
Thinkphp结合AJAX长轮询实现PC与APP推送详解
2017/07/31 PHP
JS 日期比较大小的简单实例
2014/01/13 Javascript
js数值计算时使用parseInt进行数据类型转换(jquery)
2014/10/07 Javascript
javascript高级选择器querySelector和querySelectorAll全面解析
2016/04/07 Javascript
JavaScript实现in-place思想的快速排序方法
2016/08/07 Javascript
Angularjs单选改为多选的开发过程及问题解析
2017/02/17 Javascript
jQuery插件HighCharts绘制2D圆环图效果示例【附demo源码下载】
2017/03/09 Javascript
AngularJS 最常用的八种功能(基础知识)
2017/06/26 Javascript
微信小程序 五星评分的实现实例
2017/08/04 Javascript
Node.Js中实现端口重用原理详解
2018/05/03 Javascript
Node.JS用纯JavaScript生成图片或滑块式验证码功能
2019/09/12 Javascript
vue+elementui 对话框取消 表单验证重置示例
2019/10/29 Javascript
javascript设计模式 ? 装饰模式原理与应用实例分析
2020/04/14 Javascript
[03:37]2014DOTA2国际邀请赛 主赛事第一日胜者组TOPPLAY
2014/07/19 DOTA
[01:38]DOTA2 2015国际邀请赛中国区预选赛 Showopen
2015/06/01 DOTA
分享15个最受欢迎的Python开源框架
2014/07/13 Python
python回调函数用法实例分析
2015/05/09 Python
python基础_文件操作实现全文或单行替换的方法
2017/09/04 Python
Python smtplib实现发送邮件功能
2018/05/22 Python
老生常谈python中的重载
2018/11/11 Python
TensorFlow2.X结合OpenCV 实现手势识别功能
2020/04/08 Python
django models里数据表插入数据id自增操作
2020/07/15 Python
python 实现表情识别
2020/11/21 Python
1688平价精选商城:阿里集团旗下,工厂出厂价格直销
2017/04/24 全球购物
香港万宁官方海外旗舰店:香港健与美连锁店
2018/09/27 全球购物
阿姆斯特丹杜莎夫人蜡像馆官方网站:Madame Tussauds Amsterdam
2019/03/12 全球购物
阿联酋最好的手机、电子产品和家用电器网上商店:Eros Digital Home
2020/08/09 全球购物
编辑求职信样本
2013/12/16 职场文书
工作表现自我评价
2014/02/08 职场文书
中国梦团日活动总结
2014/07/07 职场文书
党政领导班子民主生活会整改措施
2014/09/18 职场文书
2015年高考寄语或鼓励的话
2015/03/23 职场文书
在职证明书模板
2015/06/15 职场文书
纯CSS3实现div按照顺序出入效果
2021/07/15 HTML / CSS