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 相关文章推荐
JavaScript Event学习第八章 事件的顺序
Feb 07 Javascript
Web前端设计模式  制作漂亮的弹出层
Oct 29 Javascript
js window.onload 加载多个函数和追加函数详解
Jan 08 Javascript
js 通过html()及text()方法获取并设置p标签的显示值
May 14 Javascript
jquery实现的用户注册表单提示操作效果代码分享
Aug 28 Javascript
跟我学习javascript的全局变量
Nov 16 Javascript
JS设置cookie、读取cookie
Feb 24 Javascript
Web安全测试之XSS实例讲解
Aug 15 Javascript
redux.js详解及基本使用
May 24 Javascript
vue微信分享插件使用方法详解
Feb 18 Javascript
谈谈JavaScript中的垃圾回收机制
Sep 17 Javascript
JavaScript使用canvas绘制坐标和线
Apr 28 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下利用curl判断远程文件是否存在的实现代码
2011/10/08 PHP
PHP+memcache实现消息队列案例分享
2014/05/21 PHP
PHP中使用CURL模拟登录并获取数据实例
2014/07/01 PHP
PHP实现的网站目录扫描索引工具
2016/09/08 PHP
PHP实现阿里大鱼短信验证的实例代码
2017/07/10 PHP
2017年最好用的9个php开发工具推荐(超好用)
2017/10/23 PHP
flexigrid 类似ext grid的JS表格代码
2010/07/17 Javascript
jQuery '行 4954 错误: 不支持该属性或方法' 的问题解决方法
2011/01/19 Javascript
js比较和逻辑运算符的介绍
2013/03/10 Javascript
原始的js代码和jquery对比体会
2013/09/10 Javascript
基于jquery插件制作左右按钮与标题文字图片切换效果
2013/11/07 Javascript
js+html5获取用户地理位置信息并在Google地图上显示的方法
2015/06/05 Javascript
jQuery可见性过滤器:hidden和:visibility用法实例
2015/06/24 Javascript
bootstrap datetimepicker控件位置异常的解决方法
2017/11/23 Javascript
Vue cli构建及项目打包以及出现的问题解决
2018/08/27 Javascript
跟老齐学Python之模块的加载
2014/10/24 Python
python实现随机调用一个浏览器打开网页
2018/04/21 Python
python 判断字符串中是否含有汉字或非汉字的实例
2019/07/15 Python
TensorFlow实现简单的CNN的方法
2019/07/18 Python
Python 合并多个TXT文件并统计词频的实现
2019/08/23 Python
django2.2安装错误最全的解决方案(小结)
2019/09/24 Python
python 实现批量图片识别并翻译
2020/11/02 Python
英国泽西岛植物:Jersey Plants Direct
2019/08/07 全球购物
在加拿大在线租赁和购买电子游戏:Game Access
2019/09/02 全球购物
意大利奢侈品综合电商网站:MODES
2019/12/14 全球购物
销售副总经理岗位职责
2013/12/11 职场文书
火车的故事教学反思
2014/02/11 职场文书
函授生自我鉴定
2014/03/25 职场文书
投资意向书范本
2014/04/01 职场文书
优秀大学生求职自荐信范文
2014/04/19 职场文书
廉洁校园实施方案
2014/05/25 职场文书
四风问题对照检查材料整改措施
2014/09/27 职场文书
个人查摆剖析材料
2014/10/16 职场文书
工作证明英文模板
2014/10/21 职场文书
2015年语文教学工作总结
2015/05/25 职场文书
如何基于python实现单目三维重建详解
2022/06/25 Python