一个简单的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指向问题

相关文章
相关标签/搜索