之前寫過兩篇開發中遇到的問題和解決方案。當時是 CSS 和 JavaScript 分開寫的。現在寫這篇文章的時候感覺很多內容都是有內在聯絡的,所以不好分開。
給大家分享一下這半年來的感受吧:
知道和理解之間是有很大距離的。別人談到一個知識點,能接上嘴並且能發表一下自己的意見,這叫知道。遇到問題能夠想到用什麼知識點解決問題,這叫理解。
所以有很多知識點自己確實在書上都看到過但是在平時遇到問題的時候卻不知道怎麼去用或者說想到去用,有時候會有同事給一下指導說用什麼解決問題。關鍵時候還是多看(看書,看別人的程式碼)和多用。
1.display:none; 和 visibility:hidden;的區別
display:none
關閉一個元素的顯示(對佈局沒有影響);其所有後代元素都也被會被關閉顯示。文件渲染時,該元素如同不存在。(不會顯示在文件流中的位置,但是 DOM 節點仍會出現在文件流中)
visibility:hidden
visibility屬性讓你能夠控制一個圖形元素的可見性,但是仍會佔用顯示時候在文件流中的位置。
使用 display:none
的時候雖然元素不會顯示,但是DOM 節點仍會出現,所以我們就可以使用選擇器對該元素進行操作。如下圖中的示例:
2.事件冒泡引發的問題
這個問題是發生在自己上篇文章《h5端呼起攝像頭掃描二維碼並解析》中的。詳細的程式碼可以看那篇文章。
問題發生的場景
先看一段html 程式碼:
1 2 3 |
<div class="qr-btn" node-type="qr-btn">掃描二維碼1 <input node-type="jsbridge" type="file" name="myPhoto" value="掃描二維碼1" /> </div> |
之前我的想法是這個樣子的:
1.我先觸發qr-btn
的 click
事件,在回撥中觸發 input
的click
事件click
事件
2.然後觸發input
的 change
事件,獲取上傳圖片的資訊。
按照我的思路程式碼應該是下面的這個樣子的
1 2 3 4 5 6 7 8 |
//點選父級元素的事件 $('.qr-btn').bind('click',function(){ //觸發子元素的事件 $('[node-type=jsbridge]').trigger("click"); }); $('[node-type=jsbridge]').bind('change',function(){ //做一些事情 }); |
上面的程式碼,按照正常的思路應該是沒有問題的,但是,在實際的執行過程中卻發生了問題。瀏覽器的報錯資訊如下:
這是因為堆疊溢位的問題。那麼為什麼會出現這樣的問題呢?我把斷點打在了以下的位置,然後點選子元素
發生的情況是:程式碼無限次的觸發$('.qr-btn').bind(...)
,就出現了上面的報錯資訊。那麼是什麼原因導致的呢?
思考一下發現:是因為事件冒泡的問題。我單擊父元素觸發子元素的click
事件,子元素的 click
事件又冒泡到父元素上,觸發父元素的 click
事件,然後父元素再次觸發了子元素的 click
事件,這就造成了事件的迴圈。
問題解決辦法:
嘗試阻止事件的冒泡,看能夠解決問題?
那我們嘗試在觸發子元素的click
的時候,嘗試組織子元素的冒泡,看能否解決我的問題?新增如下的程式碼:
1 2 3 4 |
$('[node-type=jsbridge]').bind('click',function(e){ // console.log(e.type); e.stopPropagation(); }); |
經過我的測試,程式碼是能夠正常的執行的。
那麼我們有沒有更好的方法來解決上面的問題呢?請看接下來的內容
3.lable標籤的 for 屬性
先來看 lable
標籤的定義:
標籤為
input
元素定義標註(標記)。
label
元素不會向使用者呈現任何特殊效果。不過,它為滑鼠使用者改進了可用性。如果您在 label 元素內點選文字,就會觸發此控制元件。就是說,當使用者選擇該標籤時,瀏覽器就會自動將焦點轉到和標籤相關的表單控制元件上。
標籤的
for
屬性應當與相關元素的 id 屬性相同。
看想一下 w3school 的示例程式碼和效果:
1 2 3 4 5 |
<form> <label for="male">Male</label> <input type="radio" name="sex" id="male" /> <br /> <label for="female">Female</label> <input type="radio" name="sex" id="female" /> </form> |
效果如下圖:
到這裡應該之道我們該怎麼改進我們的程式碼了,
1 2 3 |
<lable class="qr-btn" node-type="qr-btn" for="qr-input">掃描二維碼1 <input node-type="jsbridge" id="qr-input" type="file" name="myPhoto" value="掃描二維碼1" /> </lable> |
除了 lable 標籤的樣式我們自己需要自己定義外,還有兩個優點:
- 減少了 JavaScript 的書寫;
lable
標籤和input
標籤沒有必要是包含關係
4.“彈層盒”佈局和普通盒模型佈局的優缺點對比
最近做了一個抽獎的活動,其中就有一個輪盤的旋轉的動畫效果(注意啦,中間的那個卡頓是 gif 圖片又重新開始播放了)。,效果如下圖:
關於動畫實現在下一篇文章中會繼續介紹,這裡主要來關注下佈局的問題。因為我們頁面會在 pc 和移動移動各出一套。所以在 pc 和移動我分別用了兩種方案,pc 傳統佈局實現,h5 “彈性盒”實現。
1.彈性盒實現九宮格
外圍的那些燈是使用絕對定位來做的,就不過過多的介紹,主要的是看中間的獎品九宮格的部分。html 程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<div class="re-middle"> <div class="row-a" node-type="row-a"> <div>mac pro</div> <div>掃地機器人</div> <div>iphone6s</div> </div> <div class="row-b" node-type="row-b"> <div>20積分</div> <div></div> <div>優惠券</div> </div> <div class="row-c" node-type="row-c"> <div>ps4</div> <div> <p>猴年限定</p>公仔</div> <div>祝福紅包</div> </div> <div node-type="reward-layer"></div> </div> |
css程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
.re-middle { position: absolute; width: 28.3rem; height: 16rem; top: 0; left: 0; right: 0; bottom: 0; margin: auto; background-color: #f69f75; color: #ffdece; font-size: 1.8rem; } .row-a, .row-b, .row-c { height: 5.3rem; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; -webkit-flex-flow: row nowrap; -ms-flex-flow: row nowrap; flex-flow: row nowrap; } .row-a div, .row-b div, .row-c div { -webkit-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; text-align: center; line-height: 5.3rem; background-color: #f69f75; } |
由上面的 css 程式碼可以看出來我僅僅是在水平方向上使用了“彈性盒”,而在豎直的方向上,還是使用了固定高度(因為我是用的 rem 單位,這裡的固定也是不準確的,高度會根據 fontsize 值進行計算。)
那麼可不可以在豎直和水平都是用“彈性盒”呢?
來看一下下面的css程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
.re-middle { position: absolute; width: 28.3rem; height: 16rem; top: 0; left: 0; right: 0; bottom: 0; margin: auto; background-color: #f69f75; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; -webkit-flex-direction: column; -ms-flex-direction: column; flex-direction: column; color: #ffdece; font-size: 1.8rem; } .row-a, .row-b, .row-c { /*height: 5.3rem;*/ -webkit-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; -webkit-flex-flow: row nowrap; -ms-flex-flow: row nowrap; flex-flow: row nowrap; } .row-a div, .row-b div, .row-c div { -webkit-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; text-align: center; line-height: 5.3rem; background-color: #f69f75; /*position: relative;*/ -webkit-box-align:center; -webkit-align-items:center; -ms-flex-align:center; align-items:center; } |
週末的時候關於這個佈局自己又翻書看了下“彈性盒”的文件,終於實現了在豎直和垂直方向上都實現內容的水平垂直居中內部元素。其實上面的程式碼只需要把內容的父級元素再次定義為display:flex
再新增兩個屬性justify-content
和align-items
就可以了。前者是控制彈性盒的內容垂直方向居中,後者控制內容水平方向居中。
詳細程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
.row-a div, .row-b div, .row-c div { -webkit-box-flex: 1; -webkit-flex: 1; -ms-flex: 1; flex: 1; border: 1px solid #000; -webkit-box-align: center; -webkit-align-items: center; -ms-flex-align: center; align-items: center; -webkit-box-pack: center; -webkit-justify-content: center; -ms-flex-pack: center; justify-content: center; display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; } |
2.傳統方式實現
與 h5 端相比,我在 pc 端的實現是傳統的浮動方式.我的 HTML 程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<div class="re-middle"> <div class="row-a"> <div>mac pro</div> <div class="row-a-sec">祝福紅包</div> <div class="row-a-last"> iphone 6s</div> </div> <div class="row-b clearfix"> <div>優惠券</div> <div class="row-b-sec"></div> <div class="row-b-last">20積分</div> </div> <div class="row-c"> <div>掃地機器人</div> <div class="row-c-sec">猴年限定 <p>公仔</p> </div> <div class="row-c-last">ps4</div> </div> <div class="reward-btn"></div> </div> |
css 程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
.re-middle { background-color: #f89f71; width: 530px; height: 320px; position: absolute; top: 0; right: 0; bottom: 0; left: 0; margin: auto; } .row-a, .row-b, .row-c { /*height: 106px;*/ font-size: 0; overflow: hidden; } .row-a > div, .row-c > div { float: left; width: 176px; height: 106px; text-align: center; } .row-b div { float: left; width: 176px; height: 106px; text-align: center; line-height: 106px; background-color: #f69f75; } |
由上面的 css 程式碼對比看我們可以顯然看出傳統的浮動方式的佈局和“彈性盒”佈局的一些優缺點:
float
佈局程式碼簡潔,但是必須確定的指定盒子的寬度和高度,多螢幕的適配上會差一些(rem動態計算除外)。- “彈性盒”佈局程式碼使用新的 css3屬性,需要新增額外的廠商字首,增加了程式碼的複雜度(新增廠商字首可以使用 sublime 外掛,一鍵完成,推薦我的文章 前端開發工程師的 sublime 配置)
- “彈性盒”為多螢幕的適配提供了便利性。我不用去關心子元素的寬度和高度是多少,或者是螢幕的寬度是多少,都會根據實際請款
flex
自身會去適配。
遇到的一個小問題,多行文字的處置居中:
這個九宮格內的文字元素,如果只是單行的話,只要使用 line-height
就可以解決問題,但是如果多行呢?會出什麼情況呢,看下圖:
所以這裡只能考慮不使用line-height
,使用padding
來解決問題 ,嘗試padding
後的效果。如下圖:
可以看到容器的下面多出了一部分。那也是我們使用的padding
的問題,那麼怎麼解決這個問題呢?這就要用到之前提到過的box-sizing
來解決問題。
1 2 3 4 5 6 7 8 |
.row-c-sec { color: #ffdece; font-size: 30px; padding-top: 17px; background-color: #f69f75; /*使容器的高=內容高度+padding +border*/ box-sizing: border-box; } |
5.按鈕多次提交的解決方案
在做“跑馬燈”外掛的時候遇到了一個問題,就是使用者點選開始抽獎按鈕以後在還沒有返回結果的時候使用者又第二次點選抽獎按鈕,那個時候機會出現“奇葩”的問題。比如說:第一次請求和第二次請求重合返回的結果顯示哪一個,就算允許使用者進行二次抽獎,互動也不友好。而且如果前端頁面不做限制的話,顯示也會出現奇葩的問題。比如下面這樣:
這樣是不是很糟糕啊。。。
那麼我是怎麼解決這個問題呢?
答案很簡單,我就是在點選按鈕之後,使用絕對定位彈起了一個透明的彈層,將按鈕給覆蓋,等結果返回並顯示以後,我在同時去掉彈層。這樣就避免了使用者的重複提交。詳細看一下程式碼:
1 |
<div node-type="cover_layer"></div> |
1 2 3 4 5 6 7 |
cover-layer{ width:100%; height:100%; top:0; position:absolute; z-index:9999; } |
這裡保證我的這個透明的彈層能夠覆蓋在抽獎按鈕的上面。當然這個class
是我通過JavaScript
動態的新增和刪除的。
1 2 3 4 5 6 7 8 |
$(node).on('clcik','.reward-btn',function(){ //呼起彈層 $('[node-type=cover_layer]',node).addClass('cover-layer'); ..... //返回結果以後去掉彈層 $('[node-type=cover_layer]',node).removeClass('cover-layer'); ..... }); |
這次的分享就到這裡,下一次會分享“輪盤”抽獎效果的 JavaScript 開發過程。
打賞支援我寫出更多好文章,謝謝!
打賞作者
打賞支援我寫出更多好文章,謝謝!
任選一種支付方式