CSS3选择器详解

1.常用选择器

1.1标签选择器

1
p{ }/*选择标签名为p的元素*/

1.2类选择器

1
.box{ }/*选择class名为box的元素*/

1.3ID选择器

1
#pid{ }/*选择id名为pid的元素*/

1.4通配符选择器

1
*{ }/*选择页面中所有的元素*/

1.5选择器前缀

1
div.bd{}/*选中class名为bd且标签为div的元素*/

1.6属性选择器

1
2
3
4
5
6
7
[disabled]{}/*选择带有属性disabled的所有元素*/
[type=button]{}/*选择type属性为button的所有元素*/
[class~=sports]{}/*选择class属性包含sports所有元素*/
[lang|=en]{ }/*选择以lang属性以"en"开头以及以"-"分隔的所有元素*/
a[href^="#"]{ }/*选择href属性以"#"开头的a元素*/
[href$="pdf"]{ }/*选择href属性以"pdf"结尾的元素*/
[href*="lady.163.com"]{}/*选择href属性中包含"lady.163.com"的元素*/

2.伪类选择器

2.1链接伪类

1
2
3
4
5
6
/*前两个只可用于描元素(链接)*/
a:link {color:#FF0000;} /* 未被访问的链接 */
a:visited {color:#00FF00;} /* 已被访问的链接 */
/*后两个可以用于其它元素*/
a:hover {color:#FF00FF;} /* 鼠标指针移动到链接上 */
a:active {color:#0000FF;} /* 正在被点击的链接 */

链接在进行设置时:a:hover 必须位于 a:linka:visited 之后, a:active 必须位于 a:hover 之后。

2.2动态伪类

1
2
3
4
input:focus{}/*设置input元素获得焦点后的样式*/
input:enabled{}/*元素可用的状态*/
input:disabled{}/*元素不可用的状态,属性选择器[disabled]的简写*/
input:checked{}/*单选框或者复选框选择的样式*/

2.3树形图上的伪类
html结构如下:

1
2
3
4
5
6
7
<ul>
<li>1</li>
<li>2</li>
<li><a href="#">3</a></li>
<li>4</li>
<p>5</p>
</ul>

选择符:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ul:first-child{}/*选择第一个ul下第一个标签(css2定义,支持ie7)在处理margin时很有用*/

/*以下全是CSS3新增的伪类*/
ul:last-child{}/*选择最后一个li标签*/
ul:nth-child(n){}/*选择()内的表达式如:[2n+1],或者数字所代表的li标签*/
ul:nth-last-child(n)/*同上,反向选择*/
ul:only-child{}/*选择ul只有一个子元素的项,这里会选中第三个li下的a标签*/
ul:first-of-type{}/*选择第一个该类型的标签,会选择第一个li和p*/
ul:last-of-type{}/*选择最后一个该类型的标签,会选择第四个li和p*/
ul:nth-last-of-type(2n){ }/*倒数的选择(.)内的表达式[2n],或数字所代表的该类型标签。选择第一个和第三个li标签*/
ul:only-of-type{}/*选择ul下中只有一个该类型的项,会选中a标签和p标签*/
:root{}/*选择文档的根元素*/
ul:not(li){}/*选择不含有li标签的元素,这里会选中a标签和p元素*/
ul:empty{}/*匹配ul下没有任何子元素(包括text节点)的元素,这里匹配不到,把p标签中的5删除,可匹配成功*/
E:target{}/*匹配相关URL(锚点)指向的元素。*/

3.伪元素选择器

1
2
3
4
5
6
::first-letter{}/*选择第一个字母*/
::first-line{}/*选择第一行*/
::before{content:"before";}/*在某个元素之前插入一些内容*/
::after{content:"after";}/*在某个元素后插入一些内容*/
::selection{}/*设置于被用户选中时的样式*/
::placeholder{}/*设置对象文字占位符的样式*/

4.组合选择器

4.1后代选择器

1
.main h2{  }/*选择class名为mian元素内的所有h2标签*/

4.2子选择器

1
.main>h2{  }/*选择class名为mian元素内的直接关联与父元素的h2标签*/

4.3相连选择器

1
h2~p{}/*只要P标签前有h2标签便选择*/

4.4兄弟选择器

1
h2~p{}/*选择h2标签后出现的所有p标签*/

4.4选择器分组

1
h1,h2,h3{backgound-color:#ddd;}/*同时设置h1,h2,h3标签,使用","分隔*/

5.继承

1
body{font-family:"Microsoft Yahei";}/*设置页面中所有的字体为微软雅黑*/
  • 继承属性
  • color
  • font
  • text-align
  • list-style
  • 非继承属性
  • background
  • border
  • position

6.CSS优先级

  • 计算方法
  • a = 行内样式
  • b = ID选择器的数量
  • c = 类/伪类和属性选择器的数量
  • d = 标签选择器和伪元素选择器数量

value = a1000 + b100 + c*10 +d

!important强行提升优先级

CSS之各种居中

本博客讨论居中情况设定为总宽度不定,内容宽度不定的情况。(改变大小时,仍然居中)。

特别说明:在元素设置position:absolute;来设置居中效果时,除去博客下介绍的css3方法外,还可以使用负的margin来居中,这样解决了兼容性的问题,但是只适用于宽高已知的情况(因为负的偏移量为元素宽高的一半)。宽高改变时,不再是居中效果。

在这些布局中的子元素,因为其属性设置,都默认为内容宽度。

本博客所有居中的例子,只讨论css的实现,html代码统一如下:

1
2
3
<div class="parent">
<div class="child">demo</div>
</div>

1. 水平居中

水平居中

1.1 inline-block配合text-align

1
2
3
4
5
6
.parent{
text-align: center;
}
.child{
display: inline-block;
}

优点:兼容性非常好,只需要添加只需要在子元素的css中添加*display:inline*zoom:1就可兼容到IE6、7;缺点:内部文字也会水平居中,需消除影响。

1.2 table配合margin

1
2
3
4
.child{
display:table;
margin: 0 auto;
}

优点:设置特别简单,只需对子元素进行设置,支持IE8+,需支持IE6,7时,可更换子元素为表格结构。

1.3 absolute配合transform

1
2
3
4
5
6
7
8
.parent{
position:relative;
}
.child{
position:absolute;
left:50%;
transform: translateX(-50%);
}

优点:居中元素不对其他元素产生影响。缺点:CSS3新属性支持IE9+,低版本浏览器不支持。

2. 垂直居中

垂直居中

2.1 table-cell配合vertical-align

1
2
3
4
.parent{
display: table-cell;
vertical-align:middle;
}

优点:设置简单,只需对父元素进行设置,兼容到IE8+,需兼容地版本浏览器时,可更换div为表格结构。

2.2 absolute配合tranform

1
2
3
4
5
6
7
8
.parent{
position:relative;
}
.child{
position:absolute;
top: 50%;
transform: translateY(-50%);
}

优点:居中元素不对其他元素产生影响。缺点:CSS3新属性支持IE9+,低版本浏览器不支持。

3. 水平+垂直居中

水平垂直居中

3.1 inline-block配合text-align加上table-cell配合vertical-align

1
2
3
4
5
6
7
8
.parent{
display: table-cell;
vertical-align:middle;
text-align:center;
}
.child{
display: inline-block;
}

优点:综合前两中方法,兼容性好!支持IE8+,低版本浏览器也好兼容。缺点:设置较为复杂。

3.2 absolute配合transform

1
2
3
4
5
6
7
8
9
.parent{
position: relative;
}
.child{
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
}

优点:居中元素不对其他元素产生影响。缺点:CSS3新属性支持IE9+,低版本浏览器不支持。

3.2 absolute配合margin:auto

1
2
3
4
5
6
7
8
9
10
.parent{
position: relative;
}
.child{
position: absolute;
top:0;
left:0;
right:0;
bottom:0;
}

优点:居中元素不对其他元素产生影响。缺点:CSS3新属性支持IE9+,低版本浏览器不支持。

4. 全能的flex

css3新增布局属性,布局简单,强大,性能略差,只支持IE10+,在移动端使用较多。

4.1 水平居中

1
2
3
4
5
6
7
8
9
/*当父元素设置display: flex;时,子元素为flex-item,默认为内容宽度。*/
.parent{
display: flex;
justify-content: center;
}
/* 在设置子元素为margin: 0 auto;时,可删除父元素的justify-content: center;同样可以达到居中效果*/
/* .child{
margin: 0 auto;
}*/

4.2 垂直居中

1
2
3
4
.parent{
display: flex;
align-items: center;
}

4.3 水平垂直居中

1
2
3
4
5
6
7
8
9
.parent{
display: flex;
justify-content: center;
align-items: center;
}
/*如同flex布局的第一部分一样这里也可以对子元素进行下面的设置:同时删除上面的除去display外的其他属性*/
/* .child{
margin:auto;
} */

jQuery入门笔记之(六)工具函数

工具函数直接依附于 jQuery 对象,针对 jQuery 对象本身定义的方法,它是全局性
的函数。主要提供比如字符串、数组、对象等操作方面的遍历。

字符串操作
去除字符串左右空格的工具函数:$.trim()。这个函数我在task0002的部分已经用正则实现了。
如下:

1
2
3
4
5
6
7
8
function trim(str) {
var result = "";
result = str.replace(/^\s+|\s+$/g, ""); //使用正则进行字符串替换
return result;
}
//下面是jQuery中的使用方法
var str = " guowen ";
alert($.trim(str));//可以看到空格被去除了

数组及对象操作

jQuery 为处理数组和对象提供了一些工具函数,这些函数可以便利的给数组或对象进行
遍历、筛选、搜索等操作。

遍历

这个我也实现了,其实特别简单,只不过jQuery与和我实现的方法略微有一点不同,且更强大一点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var arr = ["二狗", "甲地", "道德", "鲤鱼"];
//原生JS实现,只能用来遍历数组,不能遍历对象。
function each(arr, fn) {
for (var i = 0, l = arr.length; i < l; i++) {//遍历传参
fn(arr[i], i);//第一项为值,第二项为索引
}
}
each(arr,function(value,index) {
console.log(index+":"+value);//0:二狗1:甲地2:道德3:鲤鱼
});

//jQuery中的方法
$.each(arr, function (index,value) {//注意此处更改了参数的位置。index为数组下标,从0开始
console.log(index+":"+value);//0:二狗1:甲地2:道德3:鲤鱼
});
//$.each()还可以用来遍历对象
//<div id="box"></div>
$.each($.ajax(), function (name, fn) {
$("#box").html($("#box").html() + name + "." + "<br />");//一堆,就不贴了
})

$.grep()数据筛选

1
2
3
4
5
6
7
8
9
10
var arr = [12, 33, 4, 5, 1, 77, 55, 32];
/**
* 数据筛选函数。
* @param {String or Number} element 这里表示数组项,字符串数字都有可能(自行在函数内部进行筛选)
* @param {Number} index 表示数组下标,如下面的index<4,就只在前四项进行筛选
* @return {String or Number} 返回筛选出来的项
*/
console.log($.grep(arr,function (element,index){
return element<6&&index<4;//会打印出[4, 5]。
}));

** $.map()修改数据**

1
2
3
4
5
6
7
//还是上面的数组
var arrMap = $.map(arr,function(element, index) {
if(element<6 && index<4){
return element+1;
}
});
console.log(arrMap);//打印出[5,6]

** $.inArray()获取查找到元素的下标**

1
2
3
4
5
6
7
8
/**
* 获取查找到元素的下标
* @param {String or Number} element 需要查找的字符串或数字
* @param {Array} arr 待查找的数组
* @return {Number} 返回查找到的元素的数组下标0开始,(查找到多个时,返回第一个),未查找到时返回-1
*/
var arrInArray = $.inArray(1, arr);
console.log(arrInArray);//返回4

** $.merge()合并两个数组**

1
2
//将arr2拼接到arr后,返回合并的数组
$.merge(arr, arr2);

$.unique()删除重复的 DOM 元素(不能处理数字和字符串)
没太明白,只能删除拼接过来的重复元素,对自身的元素不受影响?文档地址
希望有看明白的教育我一下。。

发一个我实现的普通数组去重吧。(处理数字和字符串)

1
2
3
4
5
6
7
8
9
function uniqArray(arr) {//数组去重
var result = []; //创建一个新数组。
for (var i = 0, l = arr.length; i < l; i++) {
if (result.indexOf(arr[i]) === -1) { //查找是否已经含有该元素
result.push(arr[i]); //添加到新数组
}
}
return result; //返回去重后的新数组
}

** toArray()合并多个dom元素组成数组。**

1
2
3
//<ul><li>1</li><li>2</li><li>3</li><li>4</li></ul>
console.log($('li').toArray());//[[li, li, li, li]]。注意数组项是原生的DOM元素。
console.log($('li').toArray().length);//4

测试操作(类型判断)

在jQuery数据有着各种类型和状态。可以通过判断数据的类型和状态做相应的操作。

测试工具函数

函数名 说明
$.isArray(obj) 判断是否为数组对象,是返回 true
$.isFunction(obj) 判断是否为函数,是返回 true
$.isEmptyObject(obj) 判断是否为空对象,是返回 true
$.isPlainObjet(obj) 判断是否为纯粹对象,是返回 true
$.contains(obj) 判断 DOM 节点是否含另一个 DOM 节点,是返回 true
$.type(data) 判断数据类型
$.isNumeric(data) 判断数据是否为数值
$.isWindow(data) 判断数据是否为 window 对象

挑几个出来说明一下

判断是否为空对象

1
2
var obj={a:"1"};
alert($.isEmptyObject(obj));//false。

判断是由{}或 new Object()创造出的对象

1
2
alert($.isPlainObject({a:"1"}));//true
alert($.isPlainObject(new Object("a")));//false

URL解析
其实在Ajax的博客中已经讲到了:$.param()将对象键值对转换为 URL 字符串键值对

1
2
3
4
5
6
7
var obj = {
name : 'Lee',
email : "guowen921@163.com"
};
console.log( $.param(obj));//name=Lee&email=guowen921%40163.com
console.log(decodeURIComponent( $.param(obj)));//name=Lee&email=guowen921@163.com
//请注意上面的邮箱部分,$.param()会对于特殊字符进行编码传输,下面的代码,可以将其解析成字符

改变this指向
$.proxy方法类似于ECMAScript 5的bind方法,可以绑定函数的上下文(也就是this对象)和参数,返回一个新函数。
主要用处是为回调函数绑定上下文对象。如如外部事件触发调用对象方法时 this 的指向问题。

来自javaScript标准参考教程。

1
2
3
4
5
6
7
8
9
10
//<button>点击</button>
var o = {
name: "Lee",
test: function(event) {
console.log(this.name);
}
};
$("button")
.on("click", o.test) // 无输出(默认this指向触发该事件的元素也就是button)
.on("click", $.proxy(o.test, o)); // Lee,现在指向o

jQuery入门笔记之(五)jQuery中的Ajax

关于Ajax的概述就不说了,有兴趣自己去找一下吧,并且建议去我博客看关于原生js实现Ajax函数的实现,希望有所帮助。服务器的配置,那篇文章也给出了地址。
Ajax入门(一)从0开始到一次成功的GET请求
Ajax入门(二)Ajax函数封装

jQuery中的Ajax

jQuery 对 Ajax 做了大量的封装,我们使用起来也较为方便,不需要去考虑浏览器兼容性。对于封装的方式,jQuery采用了三层封装:最底层的封装方法为:$.ajax(),而通过这层封装了第二层有三种方法:.load()、$.get()和$.post(),最高层是$.getScript()和$.getJSON()方法。

Ajax中的load()方法

1
2
3
4
5
6
7
8
9
10
/**
* Ajax中的load方法(局部方法,可以直接绑定在需要获取的元素上)
* @param {String} url 必须,获取文件地址
* @param {JSON or String} 可选,键值对方式的请求参数或者(使用键值对形式,请求将转化成post)
* @param {Function} 可选,请求成功的回调函数
* @config {String} responseText 获得字符串形式的响应数据
* @config {String} textStatus 文本方式返回HTTP状态码
* @config {Object} XMLHttpRequest xhr对象,有多种属性
*/
.load(url, data, complete(responseText, textStatus, XMLHttpRequest));

例如下面这段代码

1
2
3
$('button').click(function () {
$('#box').load('test.php', {url : 'guowen'});
});

在控制台可以看到请求为POST,(注意:这里第二个参数若是字符串的情况,例如”url=guowen”,请求仍然为GET。)
所以服务器端php文件应该如此设置:

1
2
3
4
5
6
7
<?php
if ($_POST["url"] == "guowen") {//get请求把POST更改一下就好了
echo "<a href='//guowenfh.github.io/'>三省吾身丶丶</a>";
} else {
echo "其他网站";
}
?>

关于XHR对象上的属性,和HTTP状态码,参考我原来的博客。

$.get()和$.post()

.load()方法是局部方法,因为他需要一个包含元素的 jQuery 对象作为前缀。而$.get()和$.post()是全局方法,无须指定某个元素。对于用途而言,.load()适合做静态文件的异步获取,而对于需要传递参数到服务器页面的,$.get()和$.post()更加合适。

$.get()方法有四个参数,前面三个参数和.load()一样,多了一个第四参数type,即服务器返回的内容格式:包括xml、html、script、json、jsonp和text。第一个参数为必选参数,后面三个为可选参数

GET方式请求会直接在html后以?Key=value跟随,所以,有三种形式请求数据,

  1. 直接跟在url后
  2. 字符串形式的"url=guowen"
  3. 键值对形式的{url:"guowen"}

POST请求方式除去不能直接跟在url后之外,剩余两个,使用方法一样

注意:.load()方法不同的是:.load()方法根据第二个参数的不同类型,请求方式会改变,但这里已经是两个独立的方法了,所以请求类型不会进行转换。

第四个参数一般都不进行设置,jQuery会自动转换其类型。强制设置时,有可能会连标签一起返回。

至于POST与GET方式请求的差别,在我原来的博客中也有写到,这里就不赘述了。

$.getScript()$.getJSON()

jQuery提供了一组用于特定异步加载的方法:$.getScript(),用于加载特定的JS文件;$.getJSON(),用于专门加载JSON文件。

$.getJSON()方法与之前的使用方法类似,就是把第四个参数,类型强制设置成了JSON。

有时我们希望能够特定的情况再加载JS文件,而不是一开始把所有JS文件都加载了,这时就可以使用$.getScript()方法。

1
2
3
4
//点击按钮后再加载 JS 文件
$('input').click(function () {
$.getScript('test.js');
});

$.ajax()

$.ajax()是所有 ajax 方法中最底层的方法,所有其他方法都是基于$.ajax()方法的封装。这个方法只有一个参数,传递一个各个功能键值对的对象。

参数很多有兴趣的自己去看jQuery.ajax(),本来准备写几个常用的。强迫症犯了,去网上找资料做成了表格。。如下:

参数 类型 说明
url String 发送请求的地址
type String 请求方式:POST 或 GET,默认 GET
timeout Number 设置请求超时的时间(毫秒)
data Object 或String 发送到服务器的数据,键值对字符串或对象
dataType String 返回的数据类型,比如 html、xml、json 等
beforeSend Function 发送请求前可修改 XMLHttpRequest 对象的函数
complete Function 请求完成后调用的回调函数
success Function 请求成功后调用的回调函数
error Function 请求失败时调用的回调函数
global Boolean 默认为 true,表示是否触发全局 Ajax
cache Boolean 设置浏览器缓存响应,默认为 true。如果 dataType类型为 script 或 jsonp 则为 false。
content DOM 指定某个元素为与这个请求相关的所有回调函数的上下文。
contentType String 指 定 请 求 内 容 的 类 型 。 默 认 为application/x-www-form-urlencoded。
async Boolean 是否异步处理。默认为 true,false 为同步处理
processData Boolean 默认为 true,数据被处理为 URL 编码格式。如果为 false,则阻止将传入的数据处理为 URL 编码的格式。
dataFilter Function 用来筛选响应数据的回调函数。
ifModified Boolean 默认为 false,不进行头检测。如果为true,进行头检测,当相应内容与上次请求改变时,请求被认为是成功的。
jsonp String 指定一个查询参数名称来覆盖默认的 jsonp 回调参数名 callback。
username String 在 HTTP 认证请求中使用的用户名
password String 在 HTTP 认证请求中使用的密码
scriptCharset String 当远程和本地内容使用不同的字符集时,用来设置 script 和 jsonp 请求所使用的字符集。
xhr Function 用来提供 XHR 实例自定义实现的回调函数
traditional Boolean 默认为 false,不使用传统风格的参数序列化。如为 true,则使用

最常用的如下:

1
2
3
4
5
6
7
8
9
10
11
12
$('button').click(function () {
$.ajax({
type : 'POST', //这里可以换成 GET
url : 'test.php',
data : {
url : 'guowen'
},
success : function (response, stutas, xhr) {
$('#box').html(response);
}
});
});

注意:对于data属性,如果是GET、模式,可以使用三种之前说所的三种形式。如果是POST模式可以使用之前所说的两种形式。(这里不需要考虑之前的data类型的问题了,因为指定了请求类型,不会转化)

表单序列化

使用表单序列化方法.serialize(),会智能的获取指定表单内的所有元素。这样,在面对大量表单元素时,会把表单元素内容序列化为字符串,然后再使用Ajax请求。
序列化表单内的元素:data : $('form').serialize(),其余部分相同。

除此之外还可以直接获取单选框、复选框和下拉列表框等内容

除了.serialize()方法,还有一个可以返回 JSON 数据的方法:.serializeArray()。这个方法可以直接把数据整合成键值对的 JSON 对象。
使用方法相同$('form').serializeArray().

有时,我们可能会在同一个程序中多次调用$.ajax()方法。而它们很多参数都相同,这
个时候我们课时使用 jQuery 提供的$.ajaxSetup()请求默认值来初始化参数。

1
2
3
4
5
6
7
8
9
10
11
12
$('form input[type=button]').click(function () {
$.ajaxSetup({//初始化多个ajax方法相同部分参数,后面再写ajax的时候,就不用在写了。
type : 'POST',
url : 'test.php',
data : $('form').serialize()//表单序列化
});
$.ajax({
success : function (response, status, xhr) {
alert(response);
}
});
});

在使用 data 属性传递的时候,如果是以对象形式传递键值对,可以使用$.param()方法将对象转换为字符串键值对格式。

主要是针对无法直接使用表单序列化方法.serialize()的情况,且传递参数为对象,建议使用该方法进行解析后再进行传递。

Ajax进阶

加载请求,及错误处理。

主要是处理网速较慢的情况,出现请求时间较长的问题。而此时若没有一点提示,用户可能会认为你的网页出现了问题。若是能在请求过程中给用户一些提示,比如:正在努力加载中…… 。 可能会对用户更加友好一些。
jQuery提供了两个全局事件,jQuery 提供了两个全局事件,.ajaxStart().ajaxStop()
这两个全局事件,只要用户触发了 Ajax,请求开始时(未完成其他请求)激活.ajaxStart(),请求结束时(所有请求都结束了)激活.ajaxStop()
值得注意的是,因为是全局事件,所以这两个方法是直接需要直接绑定到document上的。例如:

1
2
3
4
5
$(document).ajaxStart(function(){
$(".loading").show();
}).ajaxStop(function(){
$(".loading").hide();
});

当然你也可以自行在ajax内部进行一些设置,如请求超时时间,该ajax函数是否触发全局事件等等。以键值对的方式写明就可以了。

错误处理也特别简单

1
2
3
4
5
6
7
8
$.ajax({
//…………
timeout : 500,//如果请求时间太长,可以设置超时
global : false,//如果某个 ajax 不想触发全局事件,可以设置取消
error : function(xhr,errorText,errorType){//一般都直接用xhr对象
alert("发生错误:"+xhr.status);//返回错误状态码
}
});

除此之外$.get()$.post().load(),可以通过连缀处理使用局部.error()方法来处理错误,当然还有一个全局的方法:通过全局.ajaxError()事件方法来返回错误信息。即可

请求全局事件

jQuery 对于 Ajax 操作提供了很多全局事件方法,除去上面已经提到的.ajaxStart()、.ajaxStop()、.ajaxError()等事件方法。他们都属于请求时触发的全局事件,除了这些,还有一些其他全局事件:

  1. .ajaxSuccess(),对应一个局部方法:.success(),请求成功完成时执行。
  2. .ajaxComplete(),对应一个局部方法:.complete(),请求完成后注册一个回调函数。
  3. .ajaxSend(),没有对应的局部方法,只有属性 beforeSend,请求发送之前要绑定的函数。

注意:全局事件方法是所有 Ajax 请求都会触发到,并且只能绑定在 document 上。而局部方法,则针对某个 Ajax。
对于一些全局事件方法的参数,大部分为对象,而这些对象有哪些属性或方法能调用,
可以通过遍历方法得到。如:

1
2
3
4
5
6
//遍历 settings 对象的属性
$(document).ajaxSuccess(function (event, xhr, settings) {
for (var i in settings) {
console.log(i);
}
});

这些全局方法,在$.ajax()方法中都可以直接以参数中的键值对的形式来完成

JSON和JSONP

其实在同一个域中时,只要url的后缀是json的文件的,默认就是json。当然你还可以使用$.ajax()方法设置 dataType属性加载 JSON 文件。

先来试试本地JSON:
php如下:

1
2
3
4
5
<?php
$_arr= array('a'=>1,'b'=>2,'c'=>3);
$_result = json_encode($_arr);
echo $_result;
?>

js:

1
2
3
4
5
6
7
8
$.ajax({
type:"post",
url:"test.php",
dataType:"json",//因为文件类型是php。但是返回的数据是json,所以必须设置类型,否则返回字符串
success:function(response,staus,xhr){
console.log(response.a);//打印出来1
}
});

实现跨域:这部分需要服务器端配合。

1
2
3
4
5
6
<?php
$_arr= array('a'=>1,'b'=>2,'c'=>3);
$_result = json_encode($_arr);
$_callback = $_GET['callback'];//关键在这。配合客户端JS使用
echo $_callback."($_result)";//php用点号实现字符串拼接
?>

客户端实现:

1
2
3
4
5
6
7
8
9
$.ajax({//我本地地址为http://127.0.0.1:8020/ajax.html
type:"GET",
url:"http://localhost/test.php?callback=?",//这样就可以实现跨域资源的访问了,最后的?号,jQuery会自动转化成字符串
dataType:"json",//若这里使用JSONP的话,可以删除上面url的“?callback=?”,jQuery会自动处理。
success:function(response,staus,xhr){
alert(response.a);
console.log(response)
}
});

当然我们还可以进行使用$.getJSON()。使用方式同上。

jqXHR对象

在之前,我们使用了局部方法:.success()、.complete()和.error()。这三个局部方法并不是 XMLHttpRequest 对象调用的,而是$.ajax()之类的全局方法返回的对象调用的。这个对象,就是 jqXHR 对象,它是原生对象 XHR 的一个超集。

1
2
3
4
5
6
7
8
9
//获取 jqXHR 对象,查看属性和方法
var jqXHR = $.ajax({
type : 'POST',
url : 'test.php',
data : $('form').serialize()
});
for (var i in jqXHR) {
document.write(i + '<br />');
}

注意:如果使用 jqXHR 对象的话,那么建议用.done()、.always()和.fail()代
替.success()、.complete()和.error()。以为在未来版本中,很可能将这三种方法废弃取消。

1
2
3
4
//成功后回调函数
jqXHR.done(function (response) {
$('#box').html(response);
});

使用 jqXHR 的连缀方式比$.ajax()的属性方式有三大好处:

  1. 可连缀操作,可读性大大提高;
  2. 可以多次执行同一个回调函数;
  3. 为多个操作指定回调函数;

PS:很多都只做了一下测试,并不能熟练应用,先过一遍吧,以后再来熟练掌握。

jQuery入门笔记之(四)动画效果

jQuery自带动画效果

一. 显示、隐藏

jQuery中.show()为显示方法,.hide()为隐藏方法。
在无参数的时候,只是硬性的显示内容和隐藏内容。就不用代码来演示了,.hide()方法其实就是把对象的css设为display:none;而.show()方法会保留原来的display值,并进行设置。但是在一些场景中会有所改变,在后面进行说明)。
这两个方法都可以带参数。

先来说明第一个参数:

  1. 第一种用法是传入数字,为毫秒数,表示动画过渡效果的时间。里面同时富含了匀速变大变小,以及透明度变换。
1
2
3
4
5
6
7
8
9
10
11
<button class="show">显示</button>
<button class="hide">隐藏</button>
<div id="box"></div>
<script>
$(".show").click(function() {
$("#box").show(1000);//显示用了一秒
});//可以看到很明显的动画过渡效果。
$(".hide").click(function() {
$("#box").hide(1000);
});
</script>
  1. 第二种用法是传入一个字符串。”slow”、”normal”和”fast”,分别对应600毫秒、400毫秒和200毫秒。在传入空字符串或其他字符串参数时,默认为400毫秒。
  2. 传入一个对象,后面的参数就不能填了,都在对象中。这个比较强大,整合了show()方法的多种参数实现效果外,还有一些其他的方法,比如可以动画执行中的状态,来执行函数。比较复杂,而且日常使用的话,现在这个就已经够了,在这里并不做讲述,有兴趣的可以自己参考手册。

特别注意:在传入了速度之后,内联元素inline,隐藏显示过后会变成内联块,inline-block。假设你给一个内联元素的css中设置了宽高,本来不生效,但是在执行隐藏显示后宽高生效

第二个参数:为可选参数,easing运动方式,这个参数,大部分参数值需要通过插件来使用,以后再来讲解。自带的参数有两个:”swing”(缓动)、”linear”(匀速),不填时,默认为”swing”。(注意这里传入一个错误参数,会报错)

第三个参数:可选,回调函数,第一个动画执行完毕后执行,实现链式动画。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<button class="show">显示</button>
<button class="hide">隐藏</button>
<div class="test"></div><div class="test"></div><div class="test"></div><div class="test"></div>
<script>
$('.show').click(function () {//链式动画,递归自调用
$('.test').first().show('fast', function testShow() {
$(this).next(".test").show('fast', testShow);
});//注意next中的限制条件,不然会干扰其他的元素,执行该函数。
});
$('.hide').click(function () {
$('.test').last().hide('fast', function() {
$(this).prev(".test").hide('fast', arguments.callee);
});//这里只是展现有arguments.callee这种方式,并不推荐使用,建议使用函数递归自调用
});
</script>

我们在使用.show().hide()的时候,如果需要一个按钮切换操作,需要进行一些条件判
断。而 jQuery 提供给我们一个类似功能的独立方法:.toggle()。使用方法一样。

1
2
3
$(".toggle").click(function(){
$("div").toggle("fast");
});

二. 滑动、卷动

jQuery 提供了一组改变元素高度的方法:.slideUp().slideDown().slideToggle()。顾名思义,向上收缩(卷动)和向下展开(滑动)。

1
2
3
$('.toggle').click(function () {
$('div').slideToggle();
});

注意:滑动、卷动效果和显示、隐藏效果一样,具有相同的参数。不展开讲

三. 淡入、淡出

jQuery 提供了一组专门用于透明度变化的方法:.fadeIn().fadeOut(),分别表示淡入、
淡出,当然还有一个自动切换的方法:.fadeToggle()

但是上面三个透明度方法只能是从 0 到 100,或者从 100 到 0,如果我们想设置指定值就没
有办法了。而 jQuery 为了解决这个问题提供了.fadeTo()方法,使透明度到达指定值:

1
2
3
4
5
6
$(".toggle").click(function() {
$("#box").fadeToggle('slow');
});
$(".to").click(function() {
$("#box").fadeTo('slow', 0.3);//表示30,jQuery中使用的是百分比的形式来设置
});

注意:最先点击to透明度变成0.3,再点击toggle,第一次点击隐藏,第二次点击显示透明度为0.3!(回到原有设置)

淡入、淡出和上面的显示、隐藏效果一样,具有相同参数

自定义动画

jQuery提供了上面几种简单常用的固定动画方面我们使用。但有些时候,这些简单动画无法满足我们更加复杂的需求。这个时候,jQuery 提供了一个.animate()方法来创建我们的自定义动画,满足更多复杂多变的要求。
强烈建议先看我的《JavaScript完美运动框架的进阶之旅》,使用JS基本实现了自定义动画,只不过jQuery的更加全面完善,当然也更加复杂。

必传参数只有一个,对象,实现动画:

1
2
3
4
5
$("button").click(function() {
$("#box").animate({
width: "200px",
height: "500px"});
});

这段代码已经实现了多重动画同步运动的效果,使用键值对的方式,来表明运动动画终点的位置。在实现上下左右移动时,需要结合CSS,把物体属性设置绝对定位!

第二个参数,可选,使用字符串时如同上面一样的3个值表示不同的时间(默认400ms),数字类型时,使用毫秒方式。直接跟在第一个参数之后就好
第三个参数,可选,也和上面一样,easing运动方式,自带的参数有两个:”swing”(缓动)、”linear”(匀速),不填时,默认为”swing”。(注意这里传入一个错误参数,会报错)
第四个参数,可选,回调函数,在动画执行完毕后执行,可实现链式动画。

下面进行一些特殊的说明:

自定义动画中,每次开始运动都必须是初始位置或初始状态,而有时我们想通过当前位置或状态下再进行动画。jQuery 提供了自定义动画的累加、累减功能。

1
2
3
4
5
$("button").click(function() {
$("#box").animate({//必须先设置CSS的绝对定位。
left:"+=100px"
});
});

主要是说一下自定义动画中的链式动画,有两种形式:

  1. 在回调函数中再执行一个动画,这个没什么好说的。
  2. 通过连缀或顺序来实现链式动画。

通过依次顺序实现链式动画

1
2
3
4
5
$('button').click(function () {
$('#box').animate({'left' : '100px'});
$('#box').animate({'top' : '100px'});
$('#box').animate({'width' : '300px'});
});

注意:如果不是同一个元素,就会实现同步动画

通过连缀实现链式动画

1
2
3
4
5
$('button').click(function () {
$('#box').animate({'left' : '100px'})
.animate({'top' : '100px'})
.animate({'width' : '300px'});
});

链式动画进阶

之前我们已经可以实现链式动画了,如果是同一个元素,可以依次顺序或连缀调用。如果是不同元素,可以使用回调函数。但有时链式动画太多,回调函数的可读性大大降低。为此,jQuery 提供了一组专门用于链式动画的方法。

$('#box').slideUp('slow').slideDown('slow').css('background', 'orange');这段代码中,css方法会在一开始就执行。因为动画方法可以用连缀来实现依次排列,但是css方法不是,会在一开始传入队列之前。如何解决呢?回调函数当然可以实现。

1
2
3
4
5
$('button').click(function () {
$('#box').slideUp('slow').slideDown('slow',function (){
$(this).css('background', 'orange');
});
});

这当然没问题,但是那并不是我们应该做的,因为这样可读性太差了,链式动画一多呢?原本的动画都不清晰了吧?jQuery为我们实现了一个类似回调函数的方法:.queue()。jQuery 的.queue()的回调函数可以传递一个参数,这个参数是 next 函数,在结尾处调用这个 next()方法即可再连缀执行列队动画。(不这样使用的话,后续动画效果无法实现)

1
2
3
4
5
6
7
8
9
10
11
12
$('button').click(function () {//在同一个元素直接这样写就可以了。
$('#box').slideUp('slow')
.slideDown('slow')
.queue(function (next) {
$(this).css('background', 'orange');
//next();//animate的动画效果不会生效,因为把next()注释掉了。
})
.animate({//记得设置绝对定位
height: "200px",
left: "100px"
});
});

.queue()方法还有一个功能,就是可以得到当前链式动画剩余的长度(包括当前的动画)。fx 是默认链条的参数。

1
2
3
4
//把上面的代码的第一个动画改装成如下模样时,会弹出4。
$('#box').slideUp('slow',function (){
alert($(this).queue('fx').length);
})

jQuery 还提供了一个清理链式动画的功能方法:.clearQueue()。把它放入一个链式的回调函数或.queue()方法里,就可以把剩下未执行的链条给截断。

1
2
//清理后续链式调用
$('#box').slideDown('slow', function () {$(this).clearQueue()});

动画相关方法与全局属性

停止动画
有很多时候,我们需要停止正在运行中的动画,jQuery中为此提供了一个.stop()方法。
它有三个可选参数

  1. queue 类型: String 停止链式动画的名称。(比较少用到,若存在,后两个参数都是指向该链式动画)
  2. clearQueue类型: Boolean一个布尔值,指示是否取消后续的链式动画。默认 false.
  3. jumpToEnd 类型: Boolean一个布尔值指示是否当前动画立即完成。默认false.

说明:

  1. 在无参数,且为链式动画时,调用.stop()方法,只是立即停止当前正在进行的动画,后续动画继续执行。
  2. 传入一个true时,立即停止动画,并且清空后续所有动画。
  3. 传入2个true时,立即停止,并且跳转到当前动画的结束位置,后续动画也不再执行。

代码如下:有兴趣的自行测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<button class="start">动画</button>
<button class="stop">停止</button>
<div style="position: absolute;height: 50px;width: 50px;background-color: #0B71E6;top:30px">12</div>
<script type="text/javascript">
$('.start').click(function () {
$('div').animate({'left' : '300px'}, 1000)
.animate({'top' : '300px'}, 1000)
.animate({ 'width' : '300px'}, 1000)
.animate({'height' : '300px'}, 1000);
});
$(".stop").click(function() {
$("div").stop(true,true);
});
</script>

延迟动画
有时在执行动画或链式动画时,需要在运动之前有延迟执行,jQuery 为此提供了.delay()方法。参数为延迟时间,单位为毫秒数。这个方法可以在动画之前设置延迟,也可 、以在列队动画中间加上。直接在上面代码任意地方加都可以,比较简单,自行测试吧。

获取正在进行的动画
在选择器的那篇文章中中,我们提到过一个过滤器:animated,这个过滤器可以判断出当前运动的动画是哪个元素。通过这个特点,我们可以避免由于用户快速在某个元素执行动画时,由于动画积累而导致的动画和用户的行为不一致。

对上面代码进行一些改造,将原div进行复制,添加到其后,给原div添加一个id并且在动画效果中改为该元素运动

1
2
3
4
$('.stop').click(function(){
$('div:animated').stop().css('background', 'red');
//可以看到只有运动的div背景变色,而未移动的div不改变背景色。
});

动画全局属性
jQuery 提供了两种全局设置的属性,分别为:$.fx.interval,设置每秒运行的帧数;$.fx.off,关闭页面上所有的动画。

$.fx.interval 属性可以调整动画每秒的运行帧数,默认为 13 毫秒。数字越小越流畅,但可能影响浏览器性能。
设置运行帧数为 1000 毫秒:$.fx.interval = 1000;

设置动画为关闭 true:$.fx.off = true;默认为false

jQuery入门笔记之(三)事件详解

在JavaScript 有一个非常重要的功能,就是事件驱动。如果你的网页需要与用户进行交互的话,就不可能不用到事件。它在页面完全加载后,用户通过鼠标或键盘触发页面中绑定事件的元素即可触发。jQuery为开发者更有效率的编写事件行为,封装了大量事件方法供我们使用。

基础事件

一. 绑定事件

如果你学习过原生的javascript事件,比如常用的事件:click、dblclick、mousedown、mouseup、mousemove、mouseover、mouseout等等。如果恰好你使用的是事件绑定的方式进行触发的话,一定会知道它有多么难处理,各种浏览器的兼容性,this的指向等等,但是在jQuery中,一切都不再是问题了。

jQuery 通过.bind()方法来为元素绑定这些事件。可以传递三个参数:.bind(eventType [,eventData ],handler(event))

  1. eventType:表示一个或多个DOM事件类型,比如click mouseover
  2. eventData:可选参数,表示一个对象,它包含的数据键值对映射将被传递给事件处理程序。
  3. handler(event):表示绑定到指定元素的处理函数。event表示事件对象。

下面就是绑定的几种方式:

  1. 点击按钮后执行匿名函数

    1
    2
    3
    $('button').bind('click', function() {
    alert('点击!');//使用点击事件
    });
  2. 执行普通函数式无须圆括号

    1
    2
    3
    4
    $('button').bind('click', fn);
    function fn() {//普通处理函数
    alert('点击!');
    }
  3. 可以同时绑定多个事件

    1
    2
    3
    4
    5
    $('button').bind('mouseout mouseover', function() {
    $('div').html(function(index, value) {
    return value + '1';//移入和移出分别执行一次
    });
    });
  4. 另一种方式:传递一个对象

    1
    2
    3
    4
    5
    6
    7
    8
    $('button').bind({
    'mouseout': function() { //事件名的引号可以省略
    alert('移出');
    },
    'mouseover': function() {
    alert('移入');
    }
    });

删除绑定函数:

删除绑定函数.unbind( eventType [, handler ] )有三种不同的用法:

1
2
3
4
5
$('button').unbind(); //删除当前元素的所有事件,包括匿名执行的,在js中匿名执行的事件函数无法删除。

$('button').unbind('click'); //删除当前元素的click事件,使unbind参数删除指定类型事件

$('button').unbind('click', fn1); //只删除click事件的fn1处理函数。

二. 简写事件

当然jQuery为开发者不简简单单提供了事件绑定的方法就不管其它了,为了使开发者更加方便的绑定事件,jQuery 封装了常用的事件以便节约更多的代码。我们称它为简写事件。

方法名 触发条件 描述
click(fn) 鼠标 触发每一个匹配元素的 click(单击)事件
dblclick(fn) 鼠标 触发每一个匹配元素的 dblclick(双击)事件
mousedown(fn) 鼠标 触发每一个匹配元素的 mousedown(点击后)事件
mouseup(fn) 鼠标 触发每一个匹配元素的 mouseup(点击弹起)事件
mouseover(fn) 鼠标 触发每一个匹配元素的 mouseover(鼠标移入)事件
mouseout(fn) 鼠标 触发每一个匹配元素的 mouseout(鼠标移出)事件
mousemove(fn) 鼠标 触发每一个匹配元素的mousemove(鼠标移动)事件
mouseenter(fn) 鼠标 触发每一个匹配元素的 mouseenter(鼠标穿过)事件
mouseleave(fn) 鼠标 触发每一个匹配元素的 mouseleave(鼠标穿出)事件
keydown(fn) 键盘 触发每一个匹配元素的 keydown(键盘按下)事件
keyup(fn) 键盘 触发每一个匹配元素的 keyup(键盘按下弹起)事件
keypress(fn) 键盘 触发每一个匹配元素的 keypress(键盘按下)事件
unload(fn) 文档 当卸载本页面时绑定一个要执行的函数
resize(fn) 文档 触发每一个匹配元素的 resize(文档改变大小)事件
scroll(fn) 文档 触发每一个匹配元素的 scroll(滚动条拖动)事件
focus(fn) 表单 触发每一个匹配元素的 focus(焦点激活)事件
blur(fn) 表单 触发每一个匹配元素的 blur(焦点丢失)事件
focusin(fn) 表单 触发每一个匹配元素的 focusin(焦点激活)事件
focusout(fn) 表单 触发每一个匹配元素的 focusout(焦点丢失)事件
select(fn) 表单 触发每一个匹配元素的 select(文本选定)事件
change(fn) 表单 触发每一个匹配元素的 change(值改变)事件
submit(fn) 表单 触发每一个匹配元素的 submit(表单提交)事件

大部分事件都如同上面表格中的描述一般比较简单,也比较好理解。

下面着重讲几个需要注意的地方:

  1. unload(fn)resize(fn)scroll(fn),使用$(window)对象触发。

  2. change(fn):触发的条件是,输入框的值有改变,且失去焦点。

  3. submit(fn):必须在form中,并且使用$("form")作为事件触发元素,不然无效。

  4. .mouseover().mouseout()表示鼠标移入和移出的时候触发。那么 jQuery 还封装了另外一组:.mouseenter().mouseleave()表示鼠标穿过和穿出的时候触发。那么这两组本质上有什么区别呢?
    手册上的说明是:.mouseenter().mouseleave()这组穿过子元素不会触发,而.mouseover().mouseout()则会触发。
    经过实验,代码如下:

1
2
3
4
5
6
7
8
9
10
11
<div style="width:100px;height:100px;background:blue;">
<p style="width:100px;height:50px;background:red;"></p>
</div>
<strong></strong>
<script>
$('div').mouseover(function () { //移入 div 会触发,移入 p 再触发
$('strong').html(function (index, value) {
return value+'1';
});
});
</script>

可以看到,鼠标在div内移动时,会不停触发事件函数,输出值。而mouseenter则不会有这个问题。

  1. .keydown().keyup()返回的是键码,而.keypress()返回的是字符编码。
1
2
3
4
5
6
$('input').keydown(function(e) {
alert(e.keyCode); //按下 a 返回 229
});
$('input').keypress(function(e) {
alert(e.charCode); //按下 a 返回 97
});
  1. .focus().blur()分别表示光标激活和丢失,事件触发时机是当前元素。而.focusin()
    .focusout()也表示光标激活和丢失,但是当子元素聚焦或丢失时也触发事件。
1
2
3
4
5
6
7
8
9
10
11
 <div style=style="width:100px;height:50px;background:blue;">
<input type="text">
</div>
<script>
$('div').focusin(function(e) {
alert("激活"); //绑定的是 div 元素,子类input触发
});
$('div').focusout(function(e) {
alert("丢失");
});
</script>

三. 复合事件

jQuery 提供了许多最常用的事件效果,组合一些功能实现了一些复合事件,比如切换功
能、智能加载等。

方法名 描述
ready(fn) 当 DOM 加载完毕触发事件,已经在笔记1中介绍过
hover([fn1,]fn2) 当鼠标移入触发第一个 fn1,移出触发 fn2
toggle(fn1,fn2[,fn3..]) 已废弃,当鼠标点击触发 fn1,再点击触发 fn2…
1
2
3
4
5
$('div').hover(function () {//背景移入移出切换效果
$(this).css('background', 'black'); //mouseenter 效果
}, function () {
$(this).css('background', 'red'); //mouseleave 效果,可省略
});

注意:.hover()方法是结合了.mouseenter()方法和.mouseleva()方法,并非.mouseover()
.mouseout()方法。

.toggle()有两层含义,一层就如表格中所说(1.9版移除),一层在动画中会用到,在这里不进行讲述,若想实现表格中的效果也特别简单,可以进行如下判断:

1
2
3
4
5
6
7
8
9
10
11
12
13
var flag = 1; //计数器,标记
$('div').click(function () {
if (flag == 1) { //第一次点击
$(this).css('background', 'black');
flag = 2;
} else if (flag == 2) { //第二次点击
$(this).css('background', 'blue');
flag = 3;
} else if (flag == 3) { //第三次点击
$(this).css('background', 'red');
flag = 1;
}
});

event对象

JavaScript 在事件处理函数中默认传递了 event 对象,也就是事件对象。但由于浏览器
的兼容性,开发者总是会做兼容方面的处理。jQuery 在封装的时候,解决了这些问题,并且
还创建了一些非常好用的属性和方法。

一. 事件对象

处理函数的e就是event事件对象(JS中需做兼容处理),event 对象有很多可用的属性和方法,这里先演示一下:

1
2
3
4
//通过处理函数传递事件对象
$('input').bind('click', function (e) { //接受事件对象参数
alert(e.type);//打印出click
});

下面是一些常用的属性:

属性名 描述
type 获取这个事件的事件类型的字符串,例如:click
target 获取绑定事件的 DOM 元素
dat 获取事件调用时的额外数据
relatedTarget 获取移入移出目标点离开或进入(最相邻)的那个 DOM 元素
currentTarget 获取冒泡前触发的 DOM 元素,等同与 this
pageX/pageY 获取相对于页面原点(最左上角)的水平/垂直坐标
screenX/screenY 获取显示器屏幕位置的水平/垂直坐标(非 jQuery 封装)
clientX/clientY 获取相对于页面视口的水平/垂直坐标(非 jQuery 封装)
result 获取上一个相同事件的返回值
timeStamp 获取事件触发的时间戳
whic 获取鼠标的左中右键(1,2,3),或获取键盘按键
altKey/shiftKey/ctrlKey 获取是否按下了 alt、shift、ctrl(非jQuery 封装)

注意:

target:是获取触发元素的DOM,就是你点了哪个就是哪个。
currentTarget:是获取监听元素的DOM,你把事件绑定在谁身上就是谁。

1
2
3
4
5
6
7
8
9
10
11
<div style="width:100px;height:100px;background:#999">
<p style="width:50px;height:50px;background:#333"></p>
</div>
<script>
$('div').bind('click', function (e) {
alert(e.target);//点击p时返回p
});
$('div').bind('click', function (e) {
alert(e.currentTarget);//无论何时都返回div,等同this
});
</script>

通过 event.data 获取额外数据,可以是数字、字符串、数组、对象

1
2
3
$('input').bind('click', 123, function () { //传递 data 数据
alert(e.data); //获取数字数据123
});

获取鼠标的左中右键

1
2
3
$(document).mousedown(function (e) {
alert(e.which);
});

获取键盘的按键

1
2
3
$('input').keyup(function (e) {
alert(e.which);
});

//获取触发元素鼠标当前的位置

1
2
3
$(document).click(function (e) {
alert(e.screenY+ ',' + e.pageY + ',' + e.clientY);
});

二. 冒泡和默认行为

如果看我的百度前端技术学院task0002的笔记的话,应该都知道事件冒泡是怎么样的,事件代理就是根据它来实现的。这里我稍微说一下事件冒泡是什么样的,事件冒泡其实就是在点击一个元素时,会一层一层的向父元素递进当点击一个div时其实是这样的div -> body -> html -> document

下面来看一下冒泡和默认行为的一些方法:

方法名 描述
preventDefault() 阻止某个元素的默认行为
isDefaultPrevented() 判断是否调用了 preventDefault()方法
stopPropagation() 阻止事件冒泡
isPropagationStopped() 判断是否调用了 stopPropagation()方法
stopImmediatePropagation() 阻止事件冒泡,并取消该事件的后续事件处理函数
isImmediatePropagationStopped() 判断是否调用了 stopImmediatePropagation()方法

这些方法都是event对象的一些方法,需要注意的是:
先来看到最后两个,名字都长到让人记不住的方法,,如代码中所示:

1
2
3
4
5
6
7
$("div").click(function(e) {
e.stopImmediatePropagation() ;
alert("div1");//只弹出div1
});
$("div").click(function(e) {
alert("div2");//因第一个点击事件取消了该事件的后续处理函数,这里将不被执行
});

同时取消默认行为以及事件冒泡:

1
2
3
4
5
6
7
8
9
10
11
12
<a href="//guowenfh.github.io">三省吾身丶丶</a>
<script >
$("a").click(function(e) {
// e.preventDefault();//阻止默认行为
// e.stopPropagation();//阻止事件冒泡
alert("a");
return false;
});
$(document).click(function(e) {
alert("document");
});
</script>

注意这段代码中,我们可以看到a被弹出来了,但是链接并没有跳转,而且document也没有被弹出,因为return false相当于同时了这两件事情,只不过,在使用表格中的检测方法时,返回的false。
而使用event对象的方法实现阻止时,检测返回true。

高级事件

jQuery 不但封装了大量常用的事件处理,还提供了不少高级事件方便开发者使用。比
如模拟用户触发事件、事件委托事件、和统一整合的 on 和 off,以及仅执行一次的 one 方
法。这些方法大大降低了开发者难度,提升了开发者的开发体验。

一. 模拟操作

在事件触发的时候,有时我们需要一些模拟用户行为的操作。例如:当网页加载完毕后自行点击一个按钮触发一个事件,而不是用户去点击。

1. .trigger()

先来一个最机械的.trigger()
<button>点击</button>

1
2
3
4
$("button").click(function() {
alert("这里是第一次点击来自模拟!");
});
$("button").trigger('click');

打开网页,可以看到内容并不需要被点击,就直接被弹了出来。
当然不会那么复杂,来进阶一下吧,只需要把.trigger('click')连在click事件之后就可以了,效果当然一样。
但是,这样好像还是有点麻烦,jQuery怎么可能让我们那么麻烦,把添加的字符串删除,添加.click(),现在就是这样的:

1
2
3
$('input').click(function () {
alert('我的第一次点击来自模拟!');//效果和上面一样
}).click();

这种简单的方法jQuery几乎所有的常用事件都提供了:

blur focusin mousedown resize
change focusout mousenter scroll
click keydown mouseleave select
dblclick keypress mousemove submit
error keyup mouseout unload
focus load mouseover

下面来介绍一下.trigger()的一些进阶用法,当然如果要进行这样的参数传递的话,就不能使用上面的简单方法了:
有时在模拟用户行为的时候,我们需要给事件执行传递参数,这个参数类似与在事件绑定中的event.data的额外数据,可以是数字、字符串、数组、对象。需要注意的是当传递一个值的时候,直接传递即可。当两个值以上,需要在前后用中括号包含起来。

1
2
3
$("button").click(function (e, data1, data2) {
alert(data1.a + "," + data2[1]);//加载后直接弹出1,456
}).trigger("click", [{"a" : "1", "b" : "2"}, ["123","456"]]);

在使用bind时,bind传入的额外数据通过event.data获取,该数据传输模式不变。

模拟用户行为时,除了通过 JavaScript 事件名触发,也可以通过自定义的事件触发,所谓自定义事件其实就是一个被.bind()绑定的任意函数。

1
2
3
$('input').bind('myEvent', function () {
alert('自定义事件!');
}).trigger('myEvent');

2. .triggerHandler()

这是另一个模拟用户行为的方法,用法和trigger()方法一样。但是在某些情况下有如下区别:

  1. .triggerHandler()方法并不会触发事件的默认行为,而.trigger()会,例如:

    1
    2
    $('form').trigger('submit'); //模拟用户执行提交,并跳转到执行页面
    $('form').triggerHandler('submit'); //模拟用户执行提交,并阻止的默认行为
  2. .triggerHandler()方法只会影响第一个匹配到的元素,而.trigger()会影响所有。

  3. .triggerHandler()方法会返回当前事件执行的返回值,如果没有返回值,则返回
    undefined;而.trigger()则返回当前包含事件触发元素的 jQuery 对象(方便链式连缀调用)。

  4. .trigger()在创建事件的时候,会冒泡。但这种冒泡是自定义事件才能体现出来,是
    jQuery 扩展于 DOM 的机制,并非 DOM 特性。而.triggerHandler()不会冒泡。

二. 命名空间

有时,我们想对事件进行移除。但对于同名同元素绑定的事件移除往往比较麻烦,这个
时候,可以使用事件的命名空间解决。(主要是处理绑定匿名函数的情况)

1
2
3
4
5
6
7
$("button").bind('click.abc', function(e) {
alert("abc");
});
$("button").bind('click.xyz', function(e) {
alert("xyz");
});
$("button").unbind('click.abc' );//处理过后只弹出xyz。

注意:也可以直接使用('.abc'),这样的话,可以移除相同命名空间的不同事件。对于模拟操作.trigger()和.triggerHandler(),用法也是一样的。$('input').trigger('click.abc')

三.事件委托

事件委托也就是事件代理。我在task0002(二)- DOM + 事件已经谈过了。而且也自己实现了一下事件代理,这里稍微再介绍一下:

  1. “事件代理” 的本质是利用了事件冒泡的特性。当一个元素上的事件被触发的时候,比如说鼠标点击了一个按钮,同样的事件将会在那个元素的所有祖先元素中被触发。这一过程被称为事件冒泡;
  2. 这个事件从原始元素开始一直冒泡到DOM树的最上层。任何一个事件的目标元素都是最开始的那个元素,在我们的这个例子中也就是按钮,并且它在我们的元素对象中以属性的形式出现。
  3. 使用事件代理,我们可以把事件处理器添加到一个元素上,等待一个事件从它的子级元素里冒泡上来,并且可以得知这个事件是从哪个元素开始的。
  4. 对于动态生成的节点同样有效。

实现如下:

1
2
3
4
5
6
7
8
9
10
11
<div>
<button>点击</button>
<button>点击</button>
</div>
<script>
$("div").delegate('button',"click", function() {
alert("点击了");//无论点击哪个都可以弹出
$("<button>生成</button>").appendTo('div');//点击同时生成节点,同样可以点击弹出
});
//$("div").undelegate('button', 'click');//取消事件代理
</script>

注意:.delegate()需要指定父元素,然后第一个参数是当前元素,第二个参数是事件方式,第三个参数是执行函数。和.bind()方法一样,可以传递额外参数。.undelegate().unbind()方法一样可以直接删除所有事件,比如:.undelegate('click')。也可以删除命名空间的事件,比如:.undelegate('click.abc')

开胃菜完了,下面才是重点!

强大的onoffone

目前绑定事件和解绑的方法有三组共六个。由于这三组的共存可能会造成一定的混乱,为此 jQuery1.7 以后推出了.on()和.off()方法彻底摒弃前面三组。(暂时未移除)

一. on

  1. 替代.bind()方式

    1
    2
    3
    $('button').on('click', function () {
    alert('替代.bind()');
    });
  2. 替代.bind()方式,并使用额外数据和事件对象

    1
    2
    3
    $('.button').on('click', {user : 'Lee'}, function (e) {
    alert('替代.bind()' + e.data.user);//lee
    });
  3. 替代.bind()方式,并绑定多个事件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $('.button').on('mouseover mouseout', function () {
    alert('替代.bind()移入移出!');
    });
    $('.button').on({//以对象模式绑定多个事件
    mouseover : function () {
    alert('替代.bind()移入!');
    },
    mouseout : function () {
    alert('替代.bind()移出!');
    }
    });
  4. 替代.bind()方式,阻止默认行为并取消冒泡

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $('form').on('submit', function () {
    return false;
    });
    $('form').on('submit', false);//在function中只有阻止事件存在时,这样写可以简化代码,效果相同

    $('form').on('submit', function (e) {//当然使用事件对象也是可以的
    e.preventDefault();//阻止默认行为
    e.stopPropagation();//取消冒泡
    });
  5. 替代.delegate(),事件委托

    1
    2
    3
    $('div').on('click', 'button', function () {
    $(this).clone().appendTo('div');//每次点击都复制一个button
    });

特别注意:.on().delegate()之间的选择器和事件名称的位置!因为便于多种事件处理方式,将选择器与事件名称调换了位置

二.off

  1. 替代.unbind()方式,移除事件

    1
    2
    3
    $('.button').off('click');
    $('.button').off('click', fn);
    $('.button').off('click.abc');
  2. 代替.undelegate(),取消事件委托
    $('#box').off('click', '.button');

注意:和之前方式一样,事件委托和取消事件委托也有各种搭配方式,比如额外数据、命名空间等等。

三. one

不管是.bind()还是.on(),绑定事件后都不是自动移除事件的,需要通过.unbind()和.off()来手工移除。jQuery 提供了.one()方法,绑定元素执行完毕后自动移除事件,可以方法仅触发一次的事件。

  1. 类似于.bind()只触发一次

    1
    2
    3
    $('button').one('click', function () {
    alert('one 仅触发一次!');
    });
  2. 类似于.delegate()只触发一次

    1
    2
    3
    $('div').one('click', 'button', function (){
    $(this).clone().appendTo('div');//只复制一次
    });

所以前面的一系列讲述,都是为了抛砖引玉,现在在jQuery中对于事件的处理直接用onoffone这三个就好了!

使用搜索:谷歌必应百度