《锋利的jQuery》读书笔记第四章(事件和动画)

来源:互联网 发布:过期备案域名查询工具 编辑:程序博客网 时间:2024/05/22 10:27

jQuery中的事件和动画

jQuery中的事件

加载DOM

  以浏览器装载文档为例,在页面加载完毕后,浏览器会通过JavaScript为DOM元素添加事件,在常规的 JavaScript代码中,通常使用window.onload方法,而在jQuery中,使用的是$(document).ready()方法。$(document).ready()方法是事件模块中最重要的一个函数,可以极大的提高Web应用程序的响应速度,jQuery就是用$(document).ready()方法来代替传统JavaScript的window.onload方法的。通过使用该方法,可以在DOM载入就绪时就对其进行操纵并调用执行它所绑定的函数。在使用过程中,需要注意$(document).ready()方法和window.onload()方法之间的细微区别。
1.执行时机
 $(document).ready()方法和window.onload方法有相似的功能,但是在执行时机方面是有区别的。window.onload方法是在网页所有的元素(包括元素的所有关联文件)完全加载到浏览器后才执行,即JavaScript此时才可以访问网页中的任何元素。而通过jQuery中的$(document).ready()方法注册的事件处理程序,在DOM完全就绪时就可以被调用。此时,网页的所有元素对jQuery而言都是可以访问的,但是,这并不意味着这些元素关联的文件都已经下载完毕。 举一个例子,有一个大型的图库网站,为网页中所有图片添加某些行为,例如单击图片后让它隐藏或显示。如果使用window.onload方法来处理,那么用户必须等到每一幅图片都加载完毕后,才可以进行操作。如果使用jQuery中的$(document).ready()方法来进行设置,只要DOM就绪就可以操作了,不需要等待所有图片下载完毕。很显然,把网页解析为DOM树的速度比把网页中所有的关联文件加载完毕的速度块很多。 另外,需要注意一点,由于在$(document).ready()方法内注册的事件,只要DOM就绪就会被执行,因此可能此时元素的关联文件未下载完。例如与图片的高度和宽度这样的属性此时不一定有效。要解决这个问题,可以使用jQuery中另一个关于页面加载的方法--load()方法。load()方法会在元素的onload事件中绑定一个处理事件。如果处理函数绑定给window对象,则会在所有内容(包括窗口、框架、对象和图像等)加载完毕后触发,如果处理函数绑定在元素上,则会在元素的内容加载完毕后触发。
$(window).load(function() {    //编写代码});

等价于JavaScript中的一下代码:

window.onload = function() {    //编写代码};

2.多次使用
第一章曾经用一个表格总结过window.onload方法和$(document).ready()方法的区别,现在进行详细讲解。
假设网页中有两个函数,JavaScript代码如下:

function one() {    alert("one");}function two() {    alert("two");}

当网页加载完毕后,通过如下JavaScript代码来分别调用one函数和two函数:

window.onload = one;window.onload = two;

然而当运行代码后,发现只弹出字符串“two”对话框
字符串”one”对话框不能被弹出的原因是JavaScript的onload事件一次只能保存对一个函数的引用,它会自动用后面的函数覆盖前面的函数,因此不能在现有的行为上添加新的行为。
为了达到两个函数顺序触发的效果,只能再创建一个新的JavaScript方法来实现,JavaScript代码如下:
4

window.onload = function() {    one();    two();};

虽然这样编写代码能解决某些问题,但还是不能满足某些需求,例如有多个JavaScript文件,每个文件都需要用到window.onload方法,这种情况下用上面提到的方法编写代码会非常麻烦。而jQuery的$(document).readt()方法都会在现有行为上追加新的行为,这些行为会根据注册的顺序依次执行。例如如下jQuery代码:

function one() {    alert("one");}function two() {    alert("two");}$(document).ready(function() {    one();});$(document).ready(function() {    two();});
3.简写方式
$(function() {    //编写代码});
另外,$(document)也可以简写为$().当$()不带参数时,默认参数就是"document",因此可以简写:
$().ready(function() {    //编写代码});

事件绑定

在文档装载完成后,如果打算为元素绑定事件来完成某些操作,则可以使用bind()方法来对匹配元素进行特定事件的绑定,bind()方法的调用格式为:

bind(type[,data],fn);

bind()方法有3个参数,说明如下:
第1个参数是事件类型,类型包括:blur、focus、load、resize、scroll、unload、click、dblclick、mousedown、mouseup、mousemove、mouseover、mouseout、mouseenter、mouseleave、change、select、submit、keydown、keypress、keyup和error等,当然也可以是自定义名称。
第2个参数为可选参数,作为event.data属性值传递给事件对象的额外数据对象。
第三个参数则是用来绑定处理函数。

1.基本效果

下面通过一个示例来了解bind()方法的用处。
假设网页中有一个FAQ,单击“标题”链接将显示内容。
HTML代码如下:

<div id="panel">    <h5 class="head">什么是jQuery?</h5>    <div class="content"> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx    </div></div>

按照需求,需要完成以下几个步骤。
1.等待DOM装载完毕。
2.找到“标题”所在的元素,绑定click事件。
3.找到“内容”元素,可以轻易地写出如下jQuery代码:

$(function() {    $("#panel h5.head").bind("click",function() {        $(this).next("div.content").show();    });})

与ready()方法一样,bind()方法可以多次调用。
上面jQuery代码中有一个关键字this,与在JavaScript中的作用一样,this引用的是携带相应行为的DOM元素。为了使该DOM元素能够使用jQuery中的方法,可以使用$(this)将其转换为jQuery对象。

合成事件

hover()方法
hover()方法的语法结构为:

hover(enter,leave);

hover()方法用于模拟光标悬停事件,当光标移动倒元素上时,会触发指定的第1个函数(enter),当光标移出这个元素时,会触发指定的第2个函数(leave)

$(function() {    $("#panel h5.head").hover(function() {        $(this).next("div.content").show();    },function() {        $(this).next("div.content").hide();    });});

事件冒泡

事件对象

由于IE-DOM和标准DOM实现事件对象的方法各不相同,导致在不同浏览器中获取事件对象变得比较困难。针对这个问题,jQuery进行了必要的扩展和封装,从而使得在任何浏览器中都能轻松地获取事件对象以及事件对象的一些属性。

停止事件冒泡

停止事件冒泡可以阻止事件中其他对象的事件处理函数被执行。在jQuery中提供了stopPropagation()方法来停止事件冒泡。

$('#content').bind("click",function() {    var txt = $("#msg").html() + "<p>外层div元素被单击.</p>";    $("#msg").html(txt);    event.stopPropagation();});
阻止默认事件

在jQuery中,提供了preventDefault()方法来阻止元素的默认行为。
jQuery不支持事件捕获。

事件对象的属性

1.event.type()方法

该方法的作用使可以获取到事件的类型。

$("a").click(function() {    alert("event.type");    return false;});

以上代码运行后会返回

"click"
2.event.preventDefault()方法

该方法的作用是阻止默认的事件行为。

3.event.stopPropagation()方法

该方法的作用是阻止事件的冒泡。

4.event.target()方法

该方法的作用是获取触发事件的元素。jQuery对其封装后,避免了W3C、IE和safari浏览器的不同标准差异。

5.event.relatedTarget()方法

在标准DOM中,mouseover和mouseout所发生的元素可以通过event.target()方法来访问,相关元素是通过event.relatedTarget()方法来访问的。event.relatedTarget()方法在mouseover中相当于IE浏览器的event.fromElement()方法,在mouseout中相当于IE浏览器的event.toElement方法,jQuery对其进行了封装,使之能兼容各种浏览器。

6.event.pageX()方法/event.pageY()方法

该方法的作用是获取到光标相对于页面的x坐标和y坐标。如果没有使用jQuery时,那么IE浏览器中是用event.x()/event.y()方法,而在Firefox浏览器中是用event.pageX()/event.pageY()方法。如果页面上有滚动条,则还要加上滚动条的宽度或高度。在IE浏览器中还应该减去默认的2px的边框。

7.event.which()方法

该方法的作用是在鼠标单击事件中获取鼠标的左、中、右键,在键盘事件中获取键盘的按键。

8.event.metaKey()方法

针对不同的浏览器对键盘中的ctrl按键解释不同,jQuery也进行了封装,并规定event.metaKey()方法为键盘事件中获取ctrl按键。

移除事件

可以为同一个元素绑定多个事件,也可以为多个元素绑定同一个事件。假设网页上有一个button元素,使用以下代码为该元素绑定多个相同的事件。

<script>    $(function() {        $("#btn").bind("click",function() {            $("#test").append("<p>我的绑定事件1</p>");        }).bind("click",function() {            $("#test").append("<p>我的绑定事件2</p>");        }).bind("click",function() {            $("#test").append("<p>我的绑定事件3</p>");        });        });</script><button id="btn">单击我</button><div id="test"></div>

1.移除按钮元素上以前注册的事件
首先在网页上添加一个移除事件的按钮。

<button id="delAll">删除所有事件</button>

然后为按钮绑定一个事件,jQuery代码如下:

$("#delAll").click(function() {    $("#btn").unbind("click");});

2.移除button元素的其中一个事件
首先需要为这些匿名处理函数指定一个变量。

$(function() {    $("#btn").bind("click",myFun1 = function() {        $("#test").append("<p>我的绑定事件1</p>");    }).bind("click",myFun2 = function() {        $("#test").append("<p>我的绑定事件2</p>");    }).bind("click",myFun3 = function() {        $("#test").append("<p>我的绑定事件3</p>");    });   });

然后就可以单独删除某一个事件了,jQuery代码如下:

$("#deTwo").click(function() {    $("#btn").unbind("click",myFun2);});

另外,对于只需要触发一次,随后就要立即解除绑定的情况,jQuery提供了一种间歇方法–one()方法。One()方法可以为元素绑定处理函数。当处理函数触发一次后,立即被删除。即在每个对象上,事件处理函数只会被执行一次。

模拟操作

1.常用模拟
以上的例子都是用户必须通过单击按钮,才能触发click事件,但是有时,需要通过模拟用户操作,来达到单击的效果,例如在用户进入页面后,就触发click事件,而不需要用户去主动单击。
在jQuery中,可以使用trigger()方法完成模拟操作。例如可以使用下面的代码来触发id为btn的按钮的click事件。

$("#btn").trigger("click");

也可以直接用简化写法click(),来达到同样的效果:

$("#btn").click();
2.触发自定义事件

trigger()方法不仅能触发浏览器支持的具有相同名称的事件,也可以触发自定义名称的事件,例如为元素绑定一个”myClick”的事件,jQuery代码如下:

$("#btn").bind("myClick",function() {    $("#test").append("<p>我都自定义事件.</p>");});

想要触发这个事件,可以使用如下代码来实现:

$("#btn").trigger("myClick");
3.传递数据

trigger(type[,data])方法有两个参数,第1个参数是要触发的事件类型,第2个参数是要传递给事件处理函数的附加数据,以数组形式传递。通常可以通过传递一个参数给回调函数来区别这次事件是代码触发的还是用户触发的。
下面是一个传递数据的例子。

$("#btn").bind("myClick",function() {    $("#test").append("<p>" + message1 + message2 +"</p>");});$("#btn").trigger("myClick",["我都自定义","事件"]);
4.执行默认操作

trigger()方法触发事件,会执行浏览器默认操作。

$("input").trigger("focus");

以上代码不仅会触发为input元素绑定的focus事件,也会使input元素本身得到焦点
如果只想触发绑定的focus事件,而不想执行浏览器默认操作,可以使用jQuery中另一个类似的方法–triggerHandler()方法

$("input").triggerHandler("focus");

其他用法

前面已经对bind()方法进行了介绍,bind()方法不仅能为元素绑定浏览器支持的具有相同名称的事件,也可以绑定自定义事件。不仅如此,bind()方法还能做很多事情。

1.添加事件命名空间,便于管理

例如可以把为元素绑定的多个事件类型用命名空间规范起来,jQuery代码如下:

$(function() {    $("div").bind("click.plugin",function() {        $("body").append("<p>click事件</p>");    });    $("div").bind("mouseover.plugin",function() {        $("body").append("<p>mouseover事件</p>");    });    $("div").bind("dblclick",function() {        $("body").append("<p>dblclick事件</p>");    });    $("button").click(function() {        $("div").unbind(".plugin");    });});

在所绑定的事件类型后面添加命名空间,这样在删除事件时只需要指定命名空间即可,单击button元素后,”plugin”的命名空间被删除,而不在”plugin”的命名空间的”dblclick”事件依然存在。
删除多个事件代码也可以写为以下链式代码,但显示上面的方式写的更少。

$("div").unbind("click").unbind("mouseover");
3.相同事件名称、不同命名空间执行方法

例如可以为元素绑定相同的事件类型,然后以命名空间的不同按需调用,jQuery代码如下

$(function() {    $("div").bind("click",function() {        $("body").append("<p>click事件</p>");    });    $("div").bind("click.plugin",function() {        $("body").append("<p>click.plugin事件</p>");    });    $("button").click(function() {        $("div").trigger("click!");  //注意click后面的感叹号    });});

当单击div元素后,会同时触发click事件和click.plugin事件。如果只是单击button元素,则只会触发click事件,而不触发click.plugin事件。注意,trigger(“click!”)后面的感叹号的作用是匹配所有不包含在命名空间中的click方法。
如果需要两者都被触发,改为如下代码即可:

$("div").trigger("click");

jQuery中的动画

show()方法和hide()方法

1.show()和hide()

show()方法和hide()方法是jQuery中最基本的动画方法。在HTML文档里,为一个元素用hide()方法,会将该元素的display样式改为”none”;
例如,使用如下代码隐藏element元素。

$("element").hide();

这段代码的功能与用css()方法设置display属性效果相同:

element.css("display","none");

show()方法和hide()方法在不带任何参数的情况下,相当于css(“display”,”none/block/inline”),作用是立即隐藏或显示匹配的元素,不会有任何动画。如果希望在调用show()方法时,元素慢慢地显示出来,可以为show()方法指定一个速度参数。
slow—-600毫秒;normal—-400毫秒;fast—-200毫秒

2.fadeIn()方法和fadeOut()方法

与show()方法不相同的是,fadeIn()方法和fadeOut()方法只改变元素的不透明度。fadeOut()方法会在指定的一段时间内降低元素的不透明度,直到元素完全消失(“display”,”none”)。fadeIn()方法则相反。

3.slideUp()和slideDown()方法

slideUp()方法和slideDown()方法只会改变元素的高度。如果一个元素的display属性值为”none”,当调用slideDown()方法时,这个元素将由上至下延伸显示。slideUp()方法正好相反,元素将由下到上缩短隐藏。

4.自定义动画方法animate()

前面已经讲了3种类型的动画。其中show()方法和hide()方法会同时修改元素的多个样式属性,即高度、宽度和不透明度;fadeOut()方法和fadeIn()方法只会修改元素的不透明度;slideDown()方法和slideUp()方法只会改变元素的高度。
animate()方法语法结构为:

animate(params,speed.callback);

参数说明如下:
1.params:一个包含样式属性及值的映射,比如{property1:”value1”,property2:”value2”…}
2.speed:速度参数,可选
3.callback:在动画完成时执行的函数,可选。

1.自定义简单动画

前面的几个例子,从不同的方面使元素动了起来。animate()方法也可以使元素动起来,而且animate()方法更具有灵活性。通过animate()方法,能够实现更加精致新颖的动画效果。
首先来看一个简单例子,有一个空白的HTML文档,里面有一个id=”panel”的div元素,当div元素被单击后,能在页面上横向飘动。
先给这个div元素添加css样式

#panel {    position:relative;    width:100px;    height:100px;    border:1px solid #0050d0;    background:#96e555;    cursor:pointer;}

为了使这个元素动起来,要更改元素的”left”样式属性。需要注意的是在使用animate()方法之前,为了能影响该元素的”top”、”“left”、”bottom”和”right”样式属性,必须先把元素的position样式设置为”relative”或者”absolute”。现在添加jQuery代码

$(function() {    $("#panel").click(function() {        $(this).animate({left:"500px"},3000);    });});

在本段代码中,首先为id为”panel”创建一个单击事件,然后对元素加入animate()方法,使元素在3秒(3000毫秒)内,向右移动500像素。

2.累加、累减动画

在之前的代码中,设置了{left:”500px”}作为动画参数,如果在500px之前加上”+=”或者”-=”符号即表示在当前位置累加或者累减。代码如下:

$(function() {    $("#panel").click(function() {        $(this).animate({left:"+=500px"},300); //在当前位置累加500px    });});
3.多重动画

1.同时执行多个动画。
在上面的例子中,通过控制属性left的值实现了动画的效果,这是一个很单一的动画。如果需要同时执行多个动画,例如在元素向右滑动的同时,放大元素的高度。根据animate()方法的语法结构,可以写出如下的jQuery代码。

$(function() {    $("#myImg").click(function() {        $(this).animate({left:"500px",height:"200px"},3000);    });});

运行代码后,div元素在向右滑动的同时,也会放大高度。
2.按顺序执行多个动画
上例中,两个动画效果(left:”500px”和height:”200px”)是同时发生的,如果想要按顺序执行动画,例如让div元素先向右滑动,然后再放大它的高度,只需把代码拆开,然后按照顺序写就可以了,jQuery代码如下:

$(this).animate({left:"500px"},3000);$(this).animate({height:"200px"},3000);

因为animate()方法都是对同一个jQuery对象进行操作,所以也可以改为链式的写法,代码如下:

$(this).animate({left:"500px"},3000).animate({height:"200px"},3000);

这样一来,就满足上文提出的需求了。在”left”这个定位属性改变之前,”height”属性将不会被改变。像这丫能够,动画效果的执行具有先后顺序,称为”动画队列”。
4.综合动画
接下来将完成更复杂的动画。单击div元素后让它向右移动的同时增大它的高度,并将它的不透明度从50%变换到100%,然后再让它从上到下移动,同时它的宽度变大,当完成这些效果后,让它淡出的方式隐藏。

$(function() {    $("#panel").css("opacity","0.5");    $("#panel").click(function() {        $(this).animate({left:"400px",height:"200px","opacity":"1"},3000)               .animate({top:"200px",width:"200px"},3000)               .fadeOut("slow");    });});

运行代码后,动画效果一步步执行完毕。通过这个例子可以看出,为同意元素应用多重效果后,可以通过链式方式对这些效果进行排队。

动画回调函数

在上例中,如果想在最后一步切换元素的CSS样式,而不是隐藏元素:

css("border","5px solid blue");

如果只是按照常规的方式,将fadeOut(“slow”)改为css(“border”,”5px solid blue”)并不能得到预期效果。预期的效果是在动画的最后一步改变元素的样式,而实际的效果是,刚开始执行动画的时候,css()方法就被执行了。
出现这个问题的原因是css()方法并不会加入到动画队列中,而是立即执行。可以使用回调函数(callback)对非动画方法实现排队。只要把css()方法写在最后一个动画的回调函数里即可。代码如下:

$("#panel").click(function() {    $(this).animate({left:"400px",height:"200px",opacity:"1"},3000)           .animate({top:"200px",width:"200px"},3000,function() {               $(this).css("border","5px solid blue");           })});

这样一来,css()方法就加入到动画队列中了,从而满足了上文提出的需求。
callback回调函数适用于jQuery所有的动画效果方法,例如slideDown()方法的回调函数。

$("#element").slideDown("normal",function() {    //在效果完成后做其他的事情});
停止动画和判断是否处于动画状态

1.停止元素的动画
很多时候需要停止匹配元素正在进行的动画,例如上例的动画,如果需要在某处停止动画,需要使用stop()方法。stop()方法的语法结构为:

stop([clearQueue][,gotoEnd]);

参数clearQueue和gotoEnd都是可选的参数,为Boolean值(true或false)。clearQueue代表是否清空未执行完的动画队列,gotoEnd代表是否直接将正在执行的动画跳转到末状态。
如果直接使用stop()方法,则会停止当前正在进行的动画,如果接下来还有动画等待继续进行,则以当前状态开始接下来的动画。经常会遇到这种情况,在为一个元素绑定hover事件之后,用户把光标移入元素时会触发动画效果,而这个动画还没结束时,用户就将光标移除这个元素了,那么光标移除的动画效果将会被放进队列之中,等待光标移入的动画结束后再执行。因此如果光标移入移除得过快就会导致动画动画效果与光标的动作不一致。此时只要再光标移入、移除动画之前加入stop()方法,就能解决这个问题。stop()方法会结束当前正在进行的动画,并立即执行队列中的下一个动画。以下代码就可以解决刚才的问题。

$("#panel").hover(function() {    $(this).stop()           .animate({height:"150",width:"300"},200);},function() {    $(this).stop()           .animate({height:"22",width:"60"},300);});

如果遇到组合动画,例如:

$("#panel").hover(function() {    $(this).stop()           .animate({height:"150"},200)  //如果在此时出发了光标移出的事件将执行下面的动画而非光标移出事件的动画           .animate({width:"300"},300);               },function() {        $(this).stop()               .animate({height:"22"},200)               .animate({width:"60"},300);});

此时只用一个不带参数的stop()方法就显得力不从心了。因为stop()方法只会停止正在进行的动画,如果动画正执行在第1阶段(改变height的阶段),则触发移出事件后,只会停止当前的动画,并继续进行下面的animate({width:”300”},300)动画,而光标移出事件中的动画要等这个动画结束后才会继续执行,这显然不是预期的结果。这种情况下stop()方法的第1个参数就发挥作用了,可以把第1个参数(clearQueue)设置为true,此时程序会把当前元素接下来尚未执行完的动画队列都清空。把上面的的代码改成如下代码,就能实现预期的效果。

$("#panel").hover(function() {     $(this).stop(true)            .animate({height:"150"},200) //如果在此时出发了光标移出的事件直接跳过后面的动画队列            .animate({width:"300"},300);                },function() {         $(this).stop(true)                .animate({height:"22"},200)                .animate({width:"60"},300)});

第2个参数(gotoEnd)可以用于让正在执行的动画直接到达结束时刻的状态,通常用于后一个动画需要基于前一个动画的末状态的情况,可以通过stop(false,true)这种方式来让当前动画直接到达末状态。
当然两者结合起来使用stop(true,true),即停止当前动画并直接到达当前动画的末状态,并清空动画队列。
注意,jQuery只能设置正在执行的动画的最终状态,而没有提供直接到达未执行动画队列最终状态的方法。例如有一组动画:

$("div.content")    .animate({width:"300"},200)    .animate({height:"150"},300)    .animate({opacity:".2"},2000)

无论怎么设置stop()方法,均无法在改变”width”或者”height”时,将此div元素的末状态变成300 X 150 的大小,并且设置透明度为0.2.

2.判断元素是否处于动画状态

在使用animate()方法的时候,要避免动画积累而导致的动画与用户的行为不一致。当用户快速在某个元素上执行animate()动画时,就会出现动画积累。解决方法是判断元素是否正处于动画状态,如果元素不处于动画状态,才为元素添加新的动画,否则不添加。代码如下:

if (!$(element).is(":animated")) {    //判断元素是否正处于动画状态    //如果当前没有进行动画,则添加新动画}

这个判断方法在animate()动画中经常被用到,需要特别注意。

动画方法概括

从基本动画方法hide()和show()到fadeIn()和fadeOut(),然后到slideUp()和slideDown().再到自定义动画方法animate().在介绍如此多的动画方法后,现总结概括如下:
1.改变样式属性
这里写图片描述

需要特别注意animate()方法,可以使用它来替代其他所有动画方法。
用animate()方法代替show()方法

$("p").animate({height:"show",width:"show",opacity:"show"},400)

等价于

$("p").show(400);

用animate()方法代替fadein()方法

$("p").animate({opacity:"show"},400)

等价于

$("p").fadeIn(400);

用animate()方法代替slideDown()方法

$("p").animate({height:"show"},400);

等价于

$("p").slideDown(400);

用animate()方法代替fadeTo()方法

$("p").animate({opacity:"0.6"},400)

等价于

$("p").fadeTo(400,0.6);

事实上,这些动画就是animate()方法的一种内置了特定样式属性的简写形式。在animate()方法中,这些特定样式的属性值可以为”show”、”hide”,也可以是自定义数字。

2.动画队列

1.一组元素上的动画效果
当在一个animate()方法中应用多个属性时,动画是同时发生的。
当以链式的写法应用动画方法时,动画是按照顺序发生的
2.多组元素上的动画效果
默认情况下,动画都是同时发生的。
当以回调的形式应用动画方式时,动画是按照回调顺序发生的。
另外,在动画方法中,要注意其他非动画方法会插队,例如css()方法要使非动画方法也按照顺序执行,需要把这些方法写在动画方法的回调函数中。

阅读全文
0 0