上一篇文中完成的封裝,還存在一個小問題,就是該輪播對象不能在同一頁面中重復使用,本文將通過組合使用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操作符。
這種組合使用構造函數和原型的模式,是創建自定義類型最常用的方法,至此我們就完成了這個簡單輪播對象的封裝。
以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,同時也希望多多支持武林網!
新聞熱點
疑難解答