摘要:我的第一版是這樣做的因為下和左方向的燈是需要倒序的,所以我使用了兩個倒序的循環(huán),其實當循環(huán)出現(xiàn)的時候,我們都應該思考我們的代碼是否有可優(yōu)化的空間。到這里關于跑馬燈插件的代碼解析詳和優(yōu)化就已經(jīng)完了。
既然是要編寫插件。那么叫做“插件”的東西肯定是具有的某些特征能夠滿足我們平時開發(fā)的需求或者是提高我們的開發(fā)效率。那么叫做插件的東西應該具有哪些基本特征呢?讓我們來總結一下:
1.JavaScript 插件一些基本特征:配置一定要簡單
插件中定義的變量不污染全局變量;
同一段代碼可以在不同的地方復用;
用戶可以自定義自己功能參數(shù);
具有銷毀變量和參數(shù)的功能;
如果按照以上的幾個特征來寫插件的話,我們可以總結出一個基本的代碼結構,我們一個一個的來看:
1.插件配置要盡可能的簡單html中配置容器節(jié)點
//這里的node-type="reward-area" 是標識我們插件的容器節(jié)點DOM加載完成以后初始化插件
$(function() { //這里的 test 是代表容器的 class window.LightRotate.init($("[node-type=reward-area]")); });2.插件中定義的變量不污染全局變量JavaScript 具有塊級作用域的標識符就是function了。那我們怎么聲明我們的變量才可以使它不污染全局變量呢?
這里我們需要用到的一個 JavaScript 函數(shù)的自執(zhí)行的知識點。代碼如下:(function(){ // do something })();3.在不同的地方復用功能代碼這就要用到我們面向對象的知識點,把我們的功能代碼抽象成對象,在我們需要使用的時候,實例化對象就可以了。那我們接著第二部的代碼繼續(xù)寫,
// (function($){ // 創(chuàng)建功能對象 var LightRotate = function (select) { // do something }; LightRotate.init = function (select) { var _this = this; //根據(jù)不同的容器實例化不同的對象 select.each(function () { new _this($(this)); }); }; window.LightRotate = LightRotate; })(jQuery);4.用戶可以自定義功能參數(shù)首先我們應該有默認的參數(shù)設定,比如下面這樣
// (function($){ // 創(chuàng)建功能對象 var LightRotate = function (select) { // 自定義的參數(shù) this.setting = { liAutoPlay: false, //周圍的燈是否自動旋轉 roLiSpeed: 100, //燈旋轉的速度ms roPrSpeed: 200, //獎品旋轉速度ms liDirection: true, //旋轉方向 true 正方向 false 反方向 randomPrize: false //空格是否隨機選取 }; }; LightRotate.init = function (select) { var _this = this; //根據(jù)不同的容器實例化不同的對象 select.each(function () { new _this($(this)); }); }; window.LightRotate = LightRotate; })(jQuery);其實這樣寫的話,使用者已經(jīng)可以修改我們的 JavaScript 文件來完成自定義了。但是為了能夠讓我們的差價足夠的好用,比如說,我們的使用者一點兒都不懂 js 呢?該怎么辦?
這樣我們可以把這些參數(shù)用自定義屬性配置在 html中,如下:這樣用戶只需要在 html的節(jié)點中就可以配置當前容器運行的參數(shù)。這樣的好處還可以使同一頁面上的不同容器,可以多帶帶的配置參數(shù),減少耦合。
那么在 js 中我們該怎么獲取這些參數(shù)呢?在上面的代碼中,已經(jīng)有了功能對象函數(shù)。那么我們想擴展對象方法來獲取用戶的自定義參數(shù),怎么辦呢?我們一般使用prototype的東西來擴展我們已有對象的方法,代碼如下:
// (function($){ // 創(chuàng)建功能對象 var LightRotate = function (select) { // 自定義的參數(shù) this.setting = { liAutoPlay: false, //周圍的燈是否自動旋轉 roLiSpeed: 100, //燈旋轉的速度ms roPrSpeed: 200, //獎品旋轉速度ms liDirection: true, //旋轉方向 true 正方向 false 反方向 randomPrize: false //空格是否隨機選取 }; //這里調用對象的獲取用戶自定義參數(shù)的方法,并且將默認參數(shù)合并 $.extend(_this.setting, _this.getSettingUser()); }; LightRotate.prototype = { //擴展獲取用戶自定義參數(shù)的方法 getSettingUser: function () { var userSetting = this.LightArea.attr("data-setting"); if (userSetting && userSetting !== "") { return $.parseJSON(userSetting); } else { return {}; } } }; LightRotate.init = function (select) { var _this = this; //根據(jù)不同的容器實例化不同的對象 select.each(function () { new _this($(this)); }); }; window.LightRotate = LightRotate; })(jQuery);5.銷毀變量和參數(shù)的功能;最后一個就是我們的插件應該具有銷毀自身變量和參數(shù)的功能。我們該怎么寫呢?還是在上面的代碼基礎上繼續(xù)擴展功能對象的可調用方法,代碼如下:
LightRotate.prototype = { //擴展獲取用戶自定義參數(shù)的方法 getSettingUser: function () { var userSetting = this.LightArea.attr("data-setting"); if (userSetting && userSetting !== "") { return $.parseJSON(userSetting); } else { return {}; } }, //銷毀對象參數(shù) destory: function () { $(_this.LightArea).off(); this.closeAnimation(); this.rewardTimer = null; } };由以上我們的內(nèi)容我們可以大概了解了一個成熟的插件應該具有的基本功能。
2.插件開發(fā)和優(yōu)化示例剛好這個項目是在春節(jié)放假前的一個緊急的項目,當時為了趕進度就沒有詳細思考自己的代碼結構,這樣野味自己的后續(xù)優(yōu)化提供了機會。
由上一節(jié)介紹的定時器的內(nèi)容可以知道 JavaScript 是單線程的。所以
如果一段代碼運行效率很低,就會影響后續(xù)代碼的執(zhí)行。所以對于 JavaScript ,代碼優(yōu)化是必須的。
先來看看我們的“跑馬燈”插件應該具有哪些功能:
能夠控制燈是否自動播放;
燈的旋轉方向可以控制;
燈的旋轉速度可以控制;
獎品的旋轉速度可以控制;
這里就不詳細的介紹這些功能點的開發(fā)過程,僅僅介紹優(yōu)化過程。如果有興趣可以看我文章最后附上的源代碼地址,進行下載閱讀。
1.“順序”獲取旋轉燈代碼的優(yōu)化因為周圍的燈我是使用絕對定位來做的,所以我需要“順序”的獲取他們的列表,然后操作。
首先獲取 DOM節(jié)點。
//獲取外圍的燈,可以看到我這里使用的選擇器多了一個 select,是為了獲取當前容器下的某些元素,避免有多個容器存在時沖突 this.topLight = $("[node-type=re-top]", select).find("span"); this.rightLight = $("[node-type=re-right]", select).find("span"); this.bottomLight = $("[node-type=re-bottom]", select).find("span"); this.leftLight = $("[node-type=re-left]", select).find("span");然后就應該“順序”的獲取“燈”節(jié)點的 DOM 元素列表。
我的第一版是這樣做的:
Zepto(topLight).each(function() { lightList.push(this); }); Zepto(rightLight).each(function() { lightList.push(this); }); for (var j = bottomLight.length - 1; j >= 0; j--) { lightList.push(bottomLight[j]); } for (var m = leftLight.length - 1; m >= 0; m--) { lightList.push(leftLight[m]); }因為“下”和“左”方向的燈是需要倒序的,所以我使用了兩個倒序的 for循環(huán),其實當循環(huán)出現(xiàn)的時候,我們都應該思考我們的代碼是否有可優(yōu)化的空間。
優(yōu)化后的代碼是這樣子的,在這里我減少了4次循環(huán)的使用
function () { var lightList = []; var bottomRever; var leftRever; bottomRever = Array.from(this.bottomLight).reverse(); leftRever = Array.from(this.leftLight).reverse(); lightList = Array.from(this.topLight).concat(Array.from(this.rightLight)); lightList = lightList.concat(bottomRever); lightList = lightList.concat(leftRever); }列表倒序我使用了原生 Array對象的reverse方法。
2.使用“閉包”優(yōu)化順序循環(huán)播放為了能夠使我們的“燈”順序的跑起來,第一版的思路是:
給每一個“燈”(注意,這里是每一個,罪過...罪過...)定義一個setTimeout(),執(zhí)行時間就是數(shù)序的加入 js 執(zhí)行隊列中去。
代碼是下面這樣子的:
var zepto_light = Zepto(lightList); var changeTime = 100; var lightLength = zepto_light.length; var totleTime = changeTime * lightLength; function lightOpen() { for (var i = 0; i < lightLength; i++) { (function temp(i) { lightTimer = setTimeout(function() { if (stopAnimation === false) { Zepto(zepto_light).removeClass("light_open"); Zepto(zepto_light[i]).addClass("light_open"); } else { return; } }, changeTime * i); })(i); } }這樣子寫的缺點很明顯:如果我有100個“燈”那么就會在當前的 js 執(zhí)行隊列中加入100個setTimeout(),再次強調的是我這里又使用了for循環(huán),在時間復雜度上又增加了。代碼的執(zhí)行效率又下降了。
后來思考了下,JavaScript 中“閉包”符合我當前的使用場景,就想著用閉包優(yōu)化一下,優(yōu)化后代碼如下:
lightRun: function () { var _this = this; function tempFunc() { var lightList = _this.getLightList(); var lightLength = lightList.length; var i = 0; return function () { $(lightList, _this.LightArea).removeClass("light_open"); $(lightList[i], _this.LightArea).addClass("light_open"); i++; //使一輪循環(huán)結束后能夠繼續(xù)下次循環(huán) if (i === lightLength) { i = 0; } }; } var lightRunFunc = tempFunc(); lightRunFunc(); _this.lightInterVal = setInterval(lightRunFunc, _this.setting.roLiSpeed); }由以上的代碼可以很明顯的發(fā)現(xiàn)兩個優(yōu)點:第一,就是減少了 for循環(huán)的使用,降低了代碼的時間復雜度,第二就是,每次我僅僅在當前代碼執(zhí)行的隊列中創(chuàng)建一個setInterval()。減小了執(zhí)行隊列的復雜度。
到這里關于“跑馬燈”插件的代碼解析詳和優(yōu)化就已經(jīng)完了。詳細的代碼和使用文檔請點擊鏈接。如果有什么問題可以隨時在 github 上反饋給我。
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/49745.html
相關文章
JavaScript “跑馬燈”抽獎活動代碼解析與優(yōu)化(二)
摘要:我的第一版是這樣做的因為下和左方向的燈是需要倒序的,所以我使用了兩個倒序的循環(huán),其實當循環(huán)出現(xiàn)的時候,我們都應該思考我們的代碼是否有可優(yōu)化的空間。到這里關于跑馬燈插件的代碼解析詳和優(yōu)化就已經(jīng)完了。 既然是要編寫插件。那么叫做插件的東西肯定是具有的某些特征能夠滿足我們平時開發(fā)的需求或者是提高我們的開發(fā)效率。那么叫做插件的東西應該具有哪些基本特征呢?讓我們來總結一下: 1.JavaScri...
JavaScript “跑馬燈”抽獎活動代碼解析與優(yōu)化(二)
摘要:我的第一版是這樣做的因為下和左方向的燈是需要倒序的,所以我使用了兩個倒序的循環(huán),其實當循環(huán)出現(xiàn)的時候,我們都應該思考我們的代碼是否有可優(yōu)化的空間。到這里關于跑馬燈插件的代碼解析詳和優(yōu)化就已經(jīng)完了。 既然是要編寫插件。那么叫做插件的東西肯定是具有的某些特征能夠滿足我們平時開發(fā)的需求或者是提高我們的開發(fā)效率。那么叫做插件的東西應該具有哪些基本特征呢?讓我們來總結一下: 1.JavaScri...
JavaScript “跑馬燈”抽獎活動代碼解析與優(yōu)化(一)
摘要:最近的項目中做了一個跑馬燈的抽獎特效插件。這里主要是來寫寫自己的優(yōu)化過程。所以寫代碼的時候一定要注意一些小細節(jié)哈。。。在以后,其返回的元素順序等同于在中出現(xiàn)的先后順序。盡管是一個數(shù)組。這時從加入執(zhí)行隊列到加入執(zhí)行隊列中間時間間隔是。 最近的項目中做了一個跑馬燈的抽獎特效插件。上篇文章已經(jīng)分享過html和css 的相關知識。這篇文章主要分享一些 JavaScript 相關的知識。這幾天在...
JavaScript “跑馬燈”抽獎活動代碼解析與優(yōu)化(一)
摘要:最近的項目中做了一個跑馬燈的抽獎特效插件。這里主要是來寫寫自己的優(yōu)化過程。所以寫代碼的時候一定要注意一些小細節(jié)哈。。。在以后,其返回的元素順序等同于在中出現(xiàn)的先后順序。盡管是一個數(shù)組。這時從加入執(zhí)行隊列到加入執(zhí)行隊列中間時間間隔是。 最近的項目中做了一個跑馬燈的抽獎特效插件。上篇文章已經(jīng)分享過html和css 的相關知識。這篇文章主要分享一些 JavaScript 相關的知識。這幾天在...
JavaScript “跑馬燈”抽獎活動代碼解析與優(yōu)化(一)
摘要:最近的項目中做了一個跑馬燈的抽獎特效插件。這里主要是來寫寫自己的優(yōu)化過程。所以寫代碼的時候一定要注意一些小細節(jié)哈。。。在以后,其返回的元素順序等同于在中出現(xiàn)的先后順序。盡管是一個數(shù)組。這時從加入執(zhí)行隊列到加入執(zhí)行隊列中間時間間隔是。 最近的項目中做了一個跑馬燈的抽獎特效插件。上篇文章已經(jīng)分享過html和css 的相關知識。這篇文章主要分享一些 JavaScript 相關的知識。這幾天在...
發(fā)表評論
0條評論
閱讀 1505·2021-11-22 09:34
閱讀 3320·2021-09-29 09:35
閱讀 562·2021-09-04 16:40
閱讀 2912·2019-08-30 15:53
閱讀 2582·2019-08-30 15:44
閱讀 2584·2019-08-30 14:10
閱讀 1328·2019-08-29 18:43
閱讀 2205·2019-08-29 13:26