移動端 h5開發相關內容總結(三)

以前寫過兩篇開發中遇到的問題和解決方案。當時是CSS 和 JavaScript 分開寫的。如今寫這篇文章的時候感受不少內容都是有內在聯繫的,因此很差分開。javascript

給你們分享一下這半年來的感覺吧:css

知道和理解之間是有很大距離的。別人談到一個知識點,能接上嘴而且能發表一下本身的意見,這叫知道。遇到問題可以想到用什麼知識點解決問題,這叫理解。html

因此有不少知識點本身確實在書上都看到過可是在平時遇到問題的時候殊不知道怎麼去用或者說想到去用,有時候會有同事給一下指導說用什麼解決問題。關鍵時候仍是多看(看書,看別人的代碼)和多用。前端

1.display:none; 和 visibility:hidden;的區別

display:none 關閉一個元素的顯示(對佈局沒有影響);其全部後代元素都也被會被關閉顯示。文檔渲染時,該元素如同不存在。(不會顯示在文檔流中的位置,可是 DOM 節點仍會出如今文檔流中)
visibility:hidden visibility屬性讓你可以控制一個圖形元素的可見性,可是仍會佔用顯示時候在文檔流中的位置。java

使用 display:none 的時候雖然元素不會顯示,可是DOM 節點仍會出現,因此咱們就可使用選擇器對該元素進行操做。以下圖中的示例:node

圖片描述

2.事件冒泡引起的問題

這個問題是發生在本身上篇文章《h5端呼起攝像頭掃描二維碼並解析》中的。詳細的代碼能夠看那篇文章。css3

問題發生的場景

先看一段html 代碼:git

<div class="qr-btn" node-type="qr-btn">掃描二維碼1
            <input node-type="jsbridge" type="file" name="myPhoto" value="掃描二維碼1" />
</div>

以前個人想法是這個樣子的:
1.我先觸發qr-btnclick 事件,在回調中觸發 input click 事件click 事件
2.而後觸發 inputchange 事件,獲取上傳圖片的信息。github

按照個人思路代碼應該是下面的這個樣子的web

//點擊父級元素的事件
    $('.qr-btn').bind('click',function(){
        //觸發子元素的事件
        $('[node-type=jsbridge]').trigger("click");
    });
    $('[node-type=jsbridge]').bind('change',function(){
        //作一些事情
    });

上面的代碼,按照正常的思路應該是沒有問題的,可是,在實際的運行過程當中卻發生了問題。瀏覽器的報錯信息以下:

圖片描述
這是由於堆棧溢出的問題。那麼爲何會出現這樣的問題呢?我把斷點打在瞭如下的位置,而後點擊子元素
圖片描述

發生的狀況是:代碼無限次的觸發$('.qr-btn').bind(...) ,就出現了上面的報錯信息。那麼是什麼緣由致使的呢?
思考一下發現:是由於事件冒泡的問題。我單擊父元素觸發子元素的 click 事件,子元素的 click 事件又冒泡到父元素上,觸發父元素的 click 事件,而後父元素再次觸發了子元素的 click 事件,這就形成了事件的循環

問題解決辦法:

嘗試阻止事件的冒泡,看可以解決問題?
那咱們嘗試在觸發子元素的click的時候,嘗試組織子元素的冒泡,看可否解決個人問題?添加以下的代碼:

$('[node-type=jsbridge]').bind('click',function(e){
            // console.log(e.type);
            e.stopPropagation();
        });

通過個人測試,代碼是可以正常的運行的。

那麼咱們有沒有更好的方法來解決上面的問題呢?請看接下來的內容

3.lable標籤的 for 屬性

先來看 lable 標籤的定義:

<label> 標籤爲 input 元素定義標註(標記)。

label 元素不會向用戶呈現任何特殊效果。不過,它爲鼠標用戶改進了可用性。若是您在 label 元素內點擊文本,就會觸發此控件。就是說,當用戶選擇該標籤時,瀏覽器就會自動將焦點轉到和標籤相關的表單控件上。
<label> 標籤的 for 屬性應當與相關元素的 id 屬性相同。

看想一下 w3school 的示例代碼和效果:

<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>

效果以下圖:
圖片描述

到這裏應該之道咱們該怎麼改進咱們的代碼了,

<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 代碼以下:

<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代碼以下:

.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代碼:

.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-contentalign-items就能夠了。前者是控制彈性盒的內容垂直方向居中,後者控制內容水平方向居中。

詳細代碼以下:

.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 代碼以下:

<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 代碼以下:

.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來解決問題。

.row-c-sec {
    color: #ffdece;
    font-size: 30px;
    padding-top: 17px;
    background-color: #f69f75;
    /*使容器的高=內容高度+padding +border*/
    box-sizing: border-box;
}

5.按鈕屢次提交的解決方案

在作「跑馬燈」插件的時候遇到了一個問題,就是用戶點擊開始抽獎按鈕之後在尚未返回結果的時候用戶又第二次點擊抽獎按鈕,那個時候機會出現「奇葩」的問題。好比說:第一次請求和第二次請求重合返回的結果顯示哪個,就算容許用戶進行二次抽獎,交互也不友好。並且若是前端頁面不作限制的話,顯示也會出現奇葩的問題。好比下面這樣:

圖片描述

這樣是否是很糟糕啊。。。

那麼我是怎麼解決這個問題呢?
答案很簡單,我就是在點擊按鈕以後,使用絕對定位彈起了一個透明的彈層,將按鈕給覆蓋,等結果返回並顯示之後,我在同時去掉彈層。這樣就避免了用戶的重複提交。詳細看一下代碼:

<div node-type="cover_layer"></div>
.cover-layer{
    width:100%;
    height:100%;
    top:0;
    position:absolute;
    z-index:9999;
}

這裏保證個人這個透明的彈層可以覆蓋在抽獎按鈕的上面。固然這個class 是我經過JavaScript 動態的添加和刪除的。

$(node).on('clcik','.reward-btn',function(){
    //呼起彈層
    $('[node-type=cover_layer]',node).addClass('cover-layer');
    .....

    //返回結果之後去掉彈層
    $('[node-type=cover_layer]',node).removeClass('cover-layer');
    .....
});

此次的分享就到這裏,下一次會分享「輪盤」抽獎效果的 JavaScript 開發過程。

圖片描述

相關文章
相關標籤/搜索