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 相关文章推荐
jQuery中获取checkbox选中项等操作及注意事项
Nov 24 Javascript
js 异步操作回调函数如何控制执行顺序
Dec 24 Javascript
单元选择合并变色示例代码
May 26 Javascript
AngularJS HTML DOM详解及示例代码
Aug 17 Javascript
Angular2 (RC4) 路由与导航详解
Sep 21 Javascript
浅析BootStrap中Modal(模态框)使用心得
Dec 24 Javascript
使用Bootrap和Vue实现仿百度搜索功能
Oct 26 Javascript
微信小程序获取手机网络状态的方法【附源码下载】
Dec 08 Javascript
如何用input标签和jquery实现多图片的上传和回显功能
May 16 jQuery
Layui组件Table绑定行点击事件和获取行数据的方法
Aug 19 Javascript
js canvas实现5张图片合成一张图片
Jul 15 Javascript
一文看懂如何简单实现节流函数和防抖函数
Sep 05 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处理二进制数据的实现方法
2016/06/13 PHP
通过PHP的Wrapper无缝迁移原有项目到新服务的实现方法
2020/04/02 PHP
yii2.0框架数据库操作简单示例【添加,修改,删除,查询,打印等】
2020/04/13 PHP
JavaScript下通过的XMLHttpRequest发送请求的代码
2011/06/28 Javascript
分享一个asp.net pager分页控件
2012/01/04 Javascript
博客侧边栏模块跟随滚动条滑动固定效果的实现方法(js+jquery等)
2013/03/24 Javascript
jquery数据验证插件(自制,简单,练手)实例代码
2013/10/24 Javascript
js截取字符串的两种方法及区别详解
2013/11/05 Javascript
JavaScript函数获取事件源的小例子
2014/05/14 Javascript
JavaScript中的small()方法使用详解
2015/06/08 Javascript
jQuery实现的精美平滑二级下拉菜单效果代码
2016/03/28 Javascript
jQuery技巧之让任何组件都支持类似DOM的事件管理
2016/04/05 Javascript
vue中渐进过渡效果实现
2016/10/27 Javascript
vue loadmore 组件滑动加载更多源码解析
2017/07/19 Javascript
基于ionic实现下拉刷新功能
2018/05/10 Javascript
详解在vue-test-utils中mock全局对象
2018/11/07 Javascript
vue多层嵌套路由实例分析
2019/03/19 Javascript
[01:55]《走出家门看比赛》——DOTA2 2015国际邀请赛同城线下观战
2015/07/18 DOTA
Python中类型检查的详细介绍
2017/02/13 Python
python os.path模块常用方法实例详解
2018/09/16 Python
Django之模板层的实现代码
2019/09/09 Python
PyTorch预训练的实现
2019/09/18 Python
Python 格式化输出_String Formatting_控制小数点位数的实例详解
2020/02/04 Python
python进行OpenCV实战之画图(直线、矩形、圆形)
2020/08/27 Python
Django 权限管理(permissions)与用户组(group)详解
2020/11/30 Python
美国领先的在线旅游网站:Orbitz
2018/11/05 全球购物
如何处理简单的PHP错误
2015/10/14 面试题
估算杭州有多少软件工程师
2015/08/11 面试题
小溪流的歌教学反思
2014/02/13 职场文书
生产厂长岗位职责
2014/02/21 职场文书
新闻学专业职业生涯规划范文:我的人生我做主
2014/09/12 职场文书
求职信内容一般写什么?
2015/03/20 职场文书
立案决定书范文
2015/06/24 职场文书
2015年车间管理工作总结
2015/07/23 职场文书
如何用JavaScript学习算法复杂度
2021/04/30 Javascript
Golang: 内建容器的用法
2021/05/05 Golang