一個簡單的loading效果的知識總結

原由

昨晚在慕課網的十天精通CSS3課程中,看到animation那一塊時,忽然想去張鑫旭博客看看他有沒寫一些用animation作的有趣的動畫。結果看到了一個我以前很想作,但不知道怎麼實現的效果。html

這個效果描述起來有點難度。就是平時頁面加載數據的時候可能會顯示「加載中...」,我想實現的就是後面的那個「...」,如何能讓他逐個顯示,而後循環。jquery

學了animation後,這個仍是很好實現的。但張鑫旭的效果則多了加載時間過久時,會顯示「超時」的提示語。關鍵代碼如圖,詳細代碼在這裏ajax

clipboard.png

這個很人性化啊。js代碼也不多。但問題來了,就幾行代碼,我卻沒看懂。。。
1.爲何用bind,不是都用on的嗎?bind和on有啥區別
2.setTimeout()爲何綁定的函數後面要用.bind(this)閉包

jQuery中bind和on的區別

都是用於綁定事件。若是綁定的元素已存在,那麼用哪一個均可以,沒有區別。app

注意了,是在所綁定的這個元素已經存在的前提下,二者無區別。
那若是這個元素本來是沒有的,須要點擊一個按鈕,才動態生成呢?dom

咱們看下jQuery文檔中bind和on綁定事件的語法:函數

.bind(events [,eventData], handler)動畫

.on(events [,selector] [,data], handler)this

從語法中能夠看到,.on方法比bind多了一個參數'selector'。spa

其做用是篩選出調用.on方法的dom元素的指定子元素,最經常使用的情景就是,一個ul列表,我須要點擊「添加li」按鈕後,在ul列表最後增長一個li。以下:
$('ul').on('click','li',function(){console.log('click');});

所以,.on方法的好處就在於當我用

$('ul').append('<li>我是新增的li</li>');

來動態生成新的li時,.on方法能對其這個新生成的元素綁上click事件。而.bind方法則不行,由於它的語法中沒有提供'selector'這個參數。

.on方法的這個好處就是傳說中的事件委託。將對某子元素的事件委託給其父元素,當點擊子元素時,因爲事件冒泡原理,會向上一級(即父元素)冒泡,就觸發了咱們用.on方法綁定在父元素的事件。

setTimeout中的this指向

由於感受setTimeout裏面有不少坑,因此對setTimeout很陌生。
一查才知道setTimeout傳入函數時,函數中的this指向window對象。以下:

var num = 0;
function Obj (){
    this.num = 1,
    this.getNum = function(){
        console.log(this.num);
    },
    this.getNumLater = function(){
        setTimeout(function(){
            console.log(this.num);
        }, 1000)
    }
}
var obj = new Obj; 
obj.getNum();//1  打印的是obj.num,值爲1
obj.getNumLater()//0  打印的是window.num,值爲0

能夠看到setTimeout中函數內的this是指向了window對象。由於setTimeout()調用的代碼運行在與所在函數徹底分離的執行環境上,致使這些代碼中包含的 this 關鍵字會指向 window (或全局)對象。詳細能夠看MDN setTimeout

用bind糾正setTimeout中this指向

剛開始我覺得這個bind和前面提到的bind是同一個bind。後來看了下MDN bind才發現是不一樣的。

它是Function.prototype的一個內置方法,以前提到的bind是jquery綁定事件的一個方法。

bind語法:bind(this.args,arg1[, arg2[, ...]]])
後面那段參數可能看得有點暈,不要緊,如今只要用第一個參數就行了。

看回張鑫旭那段代碼中setTimeout寫法

setTimeout(function() {
        this.ajaxing = false;
        this.innerHTML = "提交超時";
}.bind(this), 30000);

首先要清楚當前的this指的是所要點擊的a元素。

當setTimeout中的函數執行時,bind會建立一個新函數,bind的第一個參數會做爲新函數運行時的this指向,因此本來指向window的this就改成指向了當前這個this,即指向了這個a元素。

其餘方法

改變setTimeout中this指向還有兩種方法。一種是閉包,將this存到一個變量中,setTimeout中函數內部訪問這個新的變量,就能獲得當前的對象。改寫一下上面的代碼,以下:

$("#submit").bind("click", function() {
    if (!this.ajaxing) {
    var that = this;
        this.ajaxing = true;
        this.innerHTML = '提交訂單中<span class="ani_dot">...</span>';
        setTimeout(function() {
            that.ajaxing = false;
            that.innerHTML = "提交超時";
        }, 30000);
    }
});

還有一種方法是用箭頭函數,直接改寫下setTimeout便可

setTimeout(()=>{
        that.ajaxing = false;
        that.innerHTML = "提交超時";
}, 30000);

參考

jquery的bind跟on綁定事件的區別
關於setInterval和setTImeout中的this指向問題

相關文章
相關標籤/搜索