昨晚在慕课网的十天精通CSS3课程中,看到animation那一块时,忽然想去张鑫旭博客看看他有没写一些用animation作的有趣的动画。结果看到了一个我以前很想作,但不知道怎么实现的效果。html
这个效果描述起来有点难度。就是平时页面加载数据的时候可能会显示“加载中...”,我想实现的就是后面的那个“...”,如何能让他逐个显示,而后循环。jquery
学了animation后,这个仍是很好实现的。但张鑫旭的效果则多了加载时间过久时,会显示“超时”的提示语。关键代码如图,详细代码在这里。ajax
这个很人性化啊。js代码也不多。但问题来了,就几行代码,我却没看懂。。。
1.为何用bind,不是都用on的吗?bind和on有啥区别
2.setTimeout()为何绑定的函数后面要用.bind(this)闭包
都是用于绑定事件。若是绑定的元素已存在,那么用哪一个均可以,没有区别。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里面有不少坑,因此对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和前面提到的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);