jQuery的理念是: 写更少的代码, 完成更多的工作
jQuery有两个版本1.x和2.x, 版本2.x不再支持IE678
jQuery最明显的标志就是$, jQuery把所有的功能都封装在了jQuery变量中, 而$就等同于jQuery变量
可以使用jQuery.noConflict()交出$变量(在最新的3.2.1中已经删除了这个方法)
1 选择器
jQuery对象 = $(选择器);
该jQuery对象类似于数组, 数组中的每个元素是引用了的一个DOM对象
可以通过 jQuery对象.get(索引) 获得DOM对象, 又可以将DOM对象传给$()返回一个jQuery对象
返回的jQuery对象不会是undefined或者null, 最差也是一个空数组
查找得到的结果是按照顺序排列的
元素也不会被重复查找
1.1 基本选择器
1) ID查找
var div = $('#abc');
2) tag查找
var ps = $('p'); // 返回所有<p>节点
ps.length; // 数一数页面有多少个<p>节点
3) class查找
var a = $('.red'); // 所有节点包含`class="red"`都将返回
4) 属性查找
其中属性可以不加引号, 但是有空格等特殊字符时, 需要加上
var email = $('[name=email]'); // 找出<??? name="email">
var passwordInput = $('[type=password]'); // 找出<??? type="password">
var a = $('[items="A B"]'); // 找出<??? items="A B">
还可以使用前缀或者后缀查找
var icons = $('[name^=icon]'); // 找出所有name属性值以icon开头的DOM
var names = $('[name$=with]'); // 找出所有name属性值以with结尾的DOM
5) 组合查找
var emailInput = $('input[name=email]'); // 不会找出<div name="email">
var tr = $('tr.red'); // 找出<tr class="red ...">...</tr>
6) 多项查找
$('p,div'); // 把<p>和<div>都选出来
$('p.red,p.green'); // 把<p class="red">和<p class="green">都选出来
1.2 层级选择器
基本的层级选择器是用空格表示层级关系, (逗号表示多项查找)
$('form.test p input'); // 在class为test的form表单中选择被<p>包含的<input>
子选择器
限定关系必须是父子关系
$('div.main>p#test'); //选择class为main的div的子节点中id为test的p标签
过滤器
限定选择到的内容
还有一些关于表单的过滤器
:input:可以选择<input>,<textarea>,<select>和<button>;
:file:可以选择<input type="file">,和input[type=file]一样;
:checkbox:可以选择复选框,和input[type=checkbox]一样;
:radio:可以选择单选框,和input[type=radio]一样;
:focus:可以选择当前输入焦点的元素,例如把光标放到一个<input>上,用$('input:focus')就可以选出;
:checked:选择当前勾上的单选框和复选框,用这个选择器可以立刻获得用户选择的项目,如$('input[type=radio]:checked');
:enabled:可以选择可以正常输入的<input>、<select> 等,也就是没有灰掉的输入;
:disabled:和:enabled正好相反,选择那些不能输入的。
:visible : 选择可见的标签
:hidden : 选择隐藏的标签
1.3 查找过滤
使用find(选择器)来在子节点中查找
使用parent()获得父节点, next()获得下一个节点, prev()获得上一个节点, 其中next和prev还可以使用选择器
使用filter()过滤节点, 其中可以传入选择器, 也可以传入一个函数, 内含this指定为调用对象中的每个元素
使用map()可以用于处理得到的jQuery对象, 里面传入一个函数进行处理
使用first(), last(),slice(), 获得第一个, 最后一个, 和切片获取, 其中切片获取规则与python切片类似
具体使用如下:
对于HTML
<ul class="lang">
<li class="js dy">JavaScript</li>
<li class="dy">Python</li>
<li id="swift">Swift</li>
<li class="dy">Scheme</li>
<li name="haskell">Haskell</li>
</ul>
有以下操作
var ul = $('ul.lang'); // 获得<ul>
var dy = ul.find('.dy'); // 获得JavaScript, Python, Scheme
var swf = ul.find('#swift'); // 获得Swift
var hsk = ul.find('[name=haskell]'); // 获得Haskell
var swift= $('#swift'); // 获得Swift
var parent = swift.parent(); // 获得Swift的上层节点<ul>
var a = swift.parent('div.red'); // 从Swift的父节点开始向上查找,直到找到某个符合条件的节点并返回
swift.next(); // Scheme
swift.next('[name=haskell]'); // Haskell,因为Haskell是后续第一个符合选择器条件的节点
swift.prev(); // Python
swift.prev('.js'); // JavaScript,因为JavaScript是往前第一个符合选择器条件的节点
var langs = $('ul.lang li'); // 拿到JavaScript, Python, Swift, Scheme和Haskell
var a = langs.filter('.dy'); // 拿到JavaScript, Python, Scheme
var langs = $('ul.lang li'); // 拿到JavaScript, Python, Swift, Scheme和Haskell
langs.filter(function () {
return this.innerHTML.indexOf('S') === 0; // 返回S开头的节点
}); // 拿到Swift, Scheme
var langs = $('ul.lang li'); // 拿到JavaScript, Python, Swift, Scheme和Haskell
var arr = langs.map(function () {
return this.innerHTML;
}).get(); // 用get()拿到包含string的Array:['JavaScript', 'Python', 'Swift', 'Scheme', 'Haskell']
var langs = $('ul.lang li'); // 拿到JavaScript, Python, Swift, Scheme和Haskell
var js = langs.first(); // JavaScript,相当于$('ul.lang li:first-child')
var haskell = langs.last(); // Haskell, 相当于$('ul.lang li:last-child')
var sub = langs.slice(2, 4); // Swift, Scheme, 参数和数组的slice()方法一致
2 操作DOM
1) 获取和设置节点文本或者HTML文本采用text()和html()
如果不传入参数, 那么就是获取值; 如果需要设置, 那么就将设置的值传入参数
2) 修改css样式直接使用css(样式名, 样式值), 多个css可以使用链式写法
3) 操作class属性可以使用hasClass(), addClass(), removeClass()
4) 显示和隐藏元素可以直接使用show()和hide(), 隐藏后原标签的位置会被别的占领
5) 获取DOM信息
// 浏览器可视窗口大小:
$(window).width(); // 800
$(window).height(); // 600
// HTML文档大小:
$(document).width(); // 800
$(document).height(); // 3500
6) 设置和删除元素的属性
// <div id="test-div" name="Test" start="1">...</div>
var div = $('#test-div');
div.attr('data'); // undefined, 属性不存在
div.attr('name'); // 'Test'
div.attr('name', 'Hello'); // div的name属性变为'Hello'
div.removeAttr('name'); // 删除name属性
div.attr('name'); // undefined
关于radio选择
// <input id="test-radio" type="radio" name="test" checked value="1">
var radio = $('#test-radio');
radio.attr('checked'); // 'checked'
radio.prop('checked'); // true
radio.is(':checked'); // true
类似的is还可以判断:selected, 一般也是使用is而不是prop更不是attr
7) 关于表单
可以使用val()来获取和设置值
input.val(); // 'test'
input.val('abc@example.com'); // 文本框的内容已变为abc@example.com
8) 添加节点
使用append或者是prepend()
可以传入jQuery对象, DOM对象, 或者是一个函数
// 创建DOM对象:
var ps = document.createElement('li');
ps.innerHTML = '<span>Pascal</span>';
// 添加DOM对象:
ul.append(ps);
// 添加jQuery对象:
ul.append($('#scheme'));
// 添加函数对象:
ul.append(function (index, html) {
return '<li><span>Language - ' + index + '</span></li>';
});
当然也可以使用after()和before在某个节点之后或者之前添加一个元素
9) 删除节点
节点.remove() 就可以直接删除
3 事件
1) 绑定事件
jQuery对象.on("事件名", 执行函数);
jQuery对象.事件名(执行函数);
2) 解绑事件
jQuery对象.off("事件名", 指定解绑的函数)
一般地, 绑定事件的时候都是生成的匿名函数, 所以在解绑的时候是无法指定该解绑的函数的, 因此一般解绑都是省略第二个参数, 直接解绑所有该类型的事件
3) 事件触发条件
一般地, 事件触发的原则是用户自己触发, 对于文本框, 如果设置change事件, 当用JS代码去改变它的值的时候, 是不会触发change时间的
代码触发事件的方式
jQuery对象.trigger("事件名");
// 可以简写为
jQuery对象.事件名();
4) 浏览器安全限制
同样有的代码必须要用户才能执行, 例如window.open(), 直接是无法执行的, 一般的解决办法是把这个代码方法点击事件的相应函数里面
由于点击事件是用户触发的, 所以此时触发的函数内的window.open()可以被执行
5) 事件的分类
事件分为鼠标事件, 键盘事件, 其他事件
鼠标事件有:
click: 鼠标单击时触发;
dblclick:鼠标双击时触发;
mouseenter:鼠标进入时触发;
mouseleave:鼠标移出时触发;
mousemove:鼠标在DOM内部移动时触发;
hover:鼠标进入和退出时触发两个函数,相当于mouseenter加上mouseleave键盘事件有:
keydown:键盘按下时触发;
keyup:键盘松开时触发;
keypress:按一次键后触发其他事件有:
focus:当DOM获得焦点时触发;
blur:当DOM失去焦点时触发;
change:当<input>、<select>或<textarea>的内容改变时触发;
submit:当<form>提交时触发;
ready:当页面被载入并且DOM树完成初始化后触发, 且只触发一次, ready仅作用于document对象
其中由于ready事件十分的常用, 一般的写法是
$(document).ready(function () {
函数体;
});
可以简写为
$(function () {
函数体;
});
这个简写可以反复绑定事件处理函数(可以出现多个这个简写形式), 它们会一次执行
关于mousemove和keypress等函数需要获取鼠标位置按键位置等值, 所以在绑定方法的参数中可以设置一个变量e获取Event对象
$(function () {
$('#testMouseMoveDiv').mousemove(function (e) {
$('#testMouseMoveSpan').text('pageX = ' + e.pageX + ', pageY = ' + e.pageY);
});
});
4 AJAX
使用JavaScript来书写AJAX的时候需要判断浏览器的类型, 还需要判断状态和错误, 写起来十分不方便
在jQuery中绑定了一个专门用于处理的ajax()函数
$.ajax(url, settings);
其中settings是一个对象, 常用的属性有:
async:是否异步执行AJAX请求,默认为true,千万不要指定为false;
method:发送的Method,缺省为'GET',可指定为'POST'、'PUT'等;
contentType:发送POST请求的格式,默认值为'application/x-www-form-urlencoded; charset=UTF-8',也可以指定为text/plain、application/json;
data:发送的数据,可以是字符串、数组或object。如果是GET请求,data将被转换成query附加到URL上,如果是POST请求,根据contentType把data序列化成合适的格式;
headers:发送的额外的HTTP头,必须是一个object;
dataType:接收的数据格式,可以指定为'html'、'xml'、'json'、'text'等,缺省情况下根据响应的Content-Type猜测。
同时使用ajax()得到的对象其实也是一个Promise对象, 因此可以在后面加上done(), fail()和always()函数用于回调完成时, 错误时, 任何情况都要执行的函数
针对常见的请求方法, jQuery封装了ajax的常用请求方式
1) get
var jqxhr = $.get('/path/to/resource', {
name: 'Bob Lee',
check: 1
});
由于第二个参数是一个对象, 表示需要附带参数, 因此此时请求的地址就变为了
/path/to/resource?name=Bob%20Lee&check=1
这样可以省去构造请求地址
2) post
与get类似, 不过第二个参数会被序列化为application/x-www-form-urlencoded
实际的内容也会被当做post的body被发送
var jqxhr = $.post('/path/to/resource', {
name: 'Bob Lee',
check: 1
});
3) getJSON
var jqxhr = $.getJSON('/path/to/resource', {
name: 'Bob Lee',
check: 1
}).done(function (data) {
// data已经被解析为JSON对象了
});
5 扩展jQuery
可以通过扩展jQuery来实现一些自定义的方法来满足不同的需求
扩展的方式是给 $.fn 绑定
一般地
绑定的方法内可以使用this变量, 表示当前的jQuery对象, 这就保证了之后可以直接是用$().自定义函数()
绑定的方法一般会 return this; 这样才能保证链式写法的正常运行
插件函数要有默认值, 设置在$.fn.插件函数名.defaults中
还需要接受参数, 以便覆盖原有的默认值
设置高亮的插件函数实例为
// 设定默认值:
$.fn.highlight.defaults = {
color: '#d85030',
backgroundColor: '#fff8de'
}
// 设置高亮函数
$.fn.highlight = function (options) {
// 合并默认值和用户设定值:
var opts = $.extend({}, $.fn.highlight.defaults, options);
this.css('backgroundColor', opts.backgroundColor).css('color', opts.color);
return this;
}
给a标签加上判定是否需要跳转
$.fn.external = function () {
// return返回的each()返回结果,支持链式调用:
return this.filter('a').each(function () {
// 注意: each()内部的回调函数的this绑定为DOM本身!
var a = $(this);
var url = a.attr('href');
if (url && (url.indexOf('http://')===0 || url.indexOf('https://')===0)) {
a.attr('href', '#0')
.removeAttr('target')
.append(' <i class="uk-icon-external-link"></i>')
.click(function () {
if(confirm('你确定要前往' + url + '?')) {
window.open(url);
}
});
}
});
}