最近做了個項目,其中有項目需求是要實現跑馬燈抽獎效果,實現此功能主要用到js相關知識,廢話不多說,感興趣的朋友可以閱讀下全文。
開始之前先來看上篇文章遺漏的兩個問題和幾個知識點,是自己重構的過程中需要用到的:
1.移動端1px像素線的問題
對於設計師給我的手機端網頁的設計稿都是2倍圖。按照道理來說,在寫網頁的時候,所有對象的實際尺寸都是會除2。但是對於1像素的線呢?
先來看兩張圖,設計稿的效果:
在三星 S4下的實際顯示效果:
可以看到這個時候1px的線竟然顯示不出來了。這個問題是跟 S4手機的屏幕像素密度有關。關於屏幕像素密度和1px 線的關系有很多文章介紹,可以自行搜索了解。我這裡的解決方案是,對1px 的線不做處理。是多少就寫多少。就算我的基礎單位是rem,也不是其它單位。
{ position: absolute; width: 13rem; height: 9.2rem; border:1px solid #000; }
2.pc 端浏覽器和移動端浏覽器容錯率的差異
先來看一段代碼:
$('[node-type=row-a').find('div');
很明顯可以發現,我使用的選擇器是有語法錯誤的。但是在浏覽器中運行會有什麼結果呢?看下圖:
很明顯可以看出對於屬性選擇器,就算我有語法錯誤,PC 端浏覽器也是可以正確解析的。但是在手機端,這種寫法是不能夠正確解析,代碼不能夠運行。
所以寫代碼的時候一定要注意一些小細節哈。。。
3.jQuery中選擇器的使用
在使用 jQuery 或者是 Zepto 的過程中最經常使用的選擇器的寫法就是下面這樣吧,
$('div.testClass')
只是在$() 中寫上自己需要的 Dom 節點的 class或者 ID 或 者使用屬性選擇器。
在查看 jQuery的文檔,對於$()會有這樣的描述:
jQuery([selector,[context]])
最重要的是看看對 context (它也是我們平時使用中最容易忽略,但是卻非常有用的一個參數)的描述:
默認情況下, 如果沒有指定context參數,$()將在當前的 HTML document中查找 DOM 元素;如果指定了 context 參數,如一個 DOM 元素集或 jQuery 對象,那就會在這個 context 中查找。在jQuery 1.3.2以後,其返回的元素順序等同於在context中出現的先後順序。
剛開始學習 JavaScript 那會兒,就聽說了操作 DOM 是很損耗浏覽器性能,遍歷 DOM 也是很影響程序性能的。
如果我們在指定的范圍內查找需要的 Dom 會不會比從整個document 中查找快很多。而且在我們寫 web 組件的過程中,一個頁面上組件可能出現很多次,那我們怎麼判斷我們要操作哪個組件呢?這個context參數就會起到決定行的作用。具體請繼續看哇。。。
4.jQuery對象到數組的轉換
剛開始學習 jQuery的時候在一本書上看到一句話:
jQuery對象就是一個 JavaScript 數組。
而且在使用 jQuery的過程中,都會遇到,js對象轉 jQuery對象,jQuery對象轉 js對象。關於這些基礎不做過多介紹。
但是有時候我們會想在 jQuery對象上運用一些原生Array對象的方法或者屬性。來看一個簡單的例子:
由圖中的代碼運行結果,可以知道在 jQuery對象上是沒有我們要使用reverse方法的。盡管test是一個數組。
那麼我們怎麼辦才可以讓 jQuery對象使用原生的 Array對象的方法呢?
4.1使用原型鏈擴展
比如下面的代碼:
jQuery.prototype.reverse=function(){ //一些操作 }
使用prototype來擴展方法的時候,大家一直比較認為是缺點的就是可能會污染已經存在的原型鏈上的方法。還有就是訪問方法的時候需要查找原型鏈。
4.2將 jQuery對象中的對象添加到數組中
看下面的代碼
var test = $('div.test'); var a=[]; $(test).each(function(){ a.push($(this)); }); a.reverse();
這樣就可以將 jQuery對象翻轉。
4.3使用 Array對象的 from()方法
這種方法也是自己在編寫插件過程中使用的方法。看一下文檔描述:
Array.from() 方法可以將一個類數組對象或可迭代對象轉換成真實的數組。
個人感覺使用這個代碼比較簡潔。暫時還不知道有沒有性能的影響。繼續看下面的代碼:
var test = $('div.test'); var a= Array.from(test); a.reverse();
5.setInterval()和setTimeout()對程序性能的影響
因為setTimeout()和setInterval()這兩個函數在 JavaScript 中的實現機制完全一樣,這裡只拿 setTimeout()驗證
那麼來看兩段代碼
var a ={ test:function(){ setTimeout(this.bbb,1000); }, bbb:function(){ console.log('----'); } }; a.test()
輸出結果如下:
看下面的代碼輸出是什麼
var a ={ test:function(){ setTimeout(function(){ console.log(this); this.bbb(); },1000); }, bbb:function(){ console.log('----'); } }; a.test();
運行這段代碼的時候,代碼報錯
由以上的結果可以知道,當我們在使用setInterval()和setTimeout()的時候,在回掉中使用this的時候,this的作用域已經發生了改變,並且指向了 window。
setTimeout(fn,0)的含義是,指定某個任務在主線程最早可得的空閒時間執行,也就是說,盡可能早得執行。它在”任務隊列”的尾部添加一個事件,因此要等到同步任務和”任務隊列”現有的事件都處理完,才會得到執行。
意思就是說在我們設置 setTimeout()之後,也可能不是立即等待多少秒之後就立即執行回掉,而是會等待主線程的任務都處理完後再執行,所以存在 “等待”超過自己設置時間的現象。同時也會存在異步隊列中已經存在了其它的 setTimeout() 也是會等待之前的都執行完再執行當前的。
看一個 Demo:
setTimeout(function bbb(){},4000); function aaa(){ setTimeout(function ccc(){},1000); } aaa();
如果運行上面的代碼,當執行完 aaa() 等待一秒後並不會立即執行 ccc(),而是會等待 bbb() 執行完再執行 ccc() 這個時候離主線程運行結束已經4s 過去了。
以上內容是針對JavaScript實現跑馬燈抽獎活動實例代碼解析與優化(一),下篇繼續給大家分享JavaScript實現跑馬燈抽獎活動實例代碼解析與優化(二),感興趣的朋友敬請關注。