1、选择器:查找和过滤
查找:向下查找用find(), 向上查找用parent(), 同级查找用next(), prev()
过滤:和函数式编程的map、filter类似,jQuery对象也有类似的方法
filter()
方法可以过滤掉不符合选择器条件的节点:只拿到有dy类名的li元素
var langs = $('ul.lang li'); // 拿到JavaScript, Python, Swift, Scheme和Haskell var a = langs.filter('.dy');
或者传入一个函数,要特别注意函数内部的this
被绑定为DOM对象,不是jQuery对象:
var langs = $('ul.lang li'); // 拿到JavaScript, Python, Swift, Scheme和Haskell langs.filter(function () { return this.innerHTML.indexOf('S') === 0; // 返回S开头的节点 }); // 拿到Swift, Scheme
map()
方法把一个jQuery对象包含的若干DOM节点转化为其他对象:
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']
此外,一个jQuery对象如果包含了不止一个DOM节点,first()
、last()
和slice()
方法可以返回一个新的jQuery对象,把不需要的DOM节点去掉:
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操作
添加dom:html()方法暴力,一般使用append()
append除了接受字符串,append()
还可以传入原始的DOM对象,jQuery对象和函数对象:
传入函数时,要求返回一个字符串、DOM对象或者jQuery对象。因为jQuery的append()
可能作用于一组DOM节点,只有传入函数才能针对每个DOM生成不同的子节点。
append()
把DOM添加到最后,prepend()
则把DOM添加到最前。
另外注意,如果要添加的DOM节点已经存在于HTML文档中,它会首先从文档移除,然后再添加,也就是说,用append()
,你可以移动一个DOM节点。
另外,同级节点可以用after()
或者before()
方法
删除节点直接拿到jq对象调用remove()方法
3、事件
因为JavaScript在浏览器中以单线程模式运行,页面加载后,一旦页面上所有的JavaScript代码被执行完后,就只能依赖触发事件来执行JavaScript代码。
其中,ready
仅作用于document
对象。由于ready
事件在DOM完成初始化后触发,且只触发一次,所以非常适合用来写其他的初始化代码。假设我们想给一个<form>
表单绑定submit
事件
普遍这么写
$(function () { // init... });
事件参数Event,绑定的事件都会有一个自带的参数,即事件参数Event,从它上面可以获取到更多的信息
取消绑定事件:一个已被绑定的事件可以解除绑定,通过off('click', function)
实现:
function hello() { alert('hello!'); } a.click(hello); // 绑定事件 // 10秒钟后解除绑定: setTimeout(function () { a.off('click', hello); }, 10000);
需要特别注意的是,下面这种写法是无效的:
// 绑定事件: a.click(function () { alert('hello!'); }); // 解除绑定: a.off('click', function () { alert('hello!'); });
这是因为两个匿名函数虽然长得一模一样,但是它们是两个不同的函数对象,off('click', function () {...})
无法移除已绑定的第一个匿名函数。
为了实现移除效果,可以使用off('click')
一次性移除已绑定的click
事件的所有处理函数。
同理,无参数调用off()
一次性移除已绑定的所有类型的事件处理函数。
事件触发:一个需要注意的问题是,事件的触发总是由用户操作引发的,如果用JavaScript代码去改动文本框的值,将不会触发,有些时候,我们希望用代码触发change
事件,可以直接调用无参数的change()
方法来触发该事件,input.change()
相当于input.trigger('change')
,它是trigger()
方法的简写
4、动画
show / hide
直接以无参数形式调用show()
和hide()
,会显示和隐藏DOM元素。但是,只要传递一个时间参数进去,就变成了动画;时间以毫秒为单位,但也可以是'slow'
,'fast'
这些字符串;toggle()
方法则根据当前状态决定是show()
还是hide(),都可以传递时间参数
slideUp / slideDown /slideToggle()
fadeIn / fadeOut / fadeToggle()
自定义动画:animate(),需要传入的参数就是DOM元素最终的CSS状态和时间,jQuery在时间段内不断调整CSS直到达到我们设定的值
var div = $('#test-animate'); div.animate({ opacity: 0.25, '256px', height: '256px' }, 3000); // 在3秒钟内CSS过渡到设定值
animate()
还可以再传入一个函数,当动画结束时,该函数将被调用。注意:animate只能设置value为数值的css属性,比如颜色的css是不起作用的
串行动画:jQuery的动画效果还可以串行执行,通过delay()
方法还可以实现暂停,这样,我们可以实现更复杂的动画效果
var div = $('#test-animates'); // 动画效果:slideDown - 暂停 - 放大 - 暂停 - 缩小 div.slideDown(2000) .delay(1000) .animate({ '256px', height: '256px' }, 2000) .delay(1000) .animate({ '128px', height: '128px' }, 2000); }
此外,jQuery也没有实现对background-color
的动画效果,用animate()
设置background-color
也没有效果。这种情况下可以使用CSS3的transition
实现动画效果
5、AJAX
可以是用es6的Promise来写ajax的回调函数
'use strict'; function ajaxLog(s) { var txt = $('#test-response-text'); txt.val(txt.val() + ' ' + s); } $('#test-response-text').val(''); var jqxhr = $.ajax('/api/categories', { dataType: 'json' }).done(function (data) { ajaxLog('成功, 收到的数据: ' + JSON.stringify(data)); }).fail(function (xhr, status) { ajaxLog('失败: ' + xhr.status + ', 原因: ' + status); }).always(function () { ajaxLog('请求完成: 无论成功或失败都会调用'); });
get方法:第二个参数如果是object,jQuery自动把它变成query string然后加到URL后面
var jqxhr = $.get('/path/to/resource', { name: 'Bob Lee', check: 1 });
getJSON
由于JSON用得越来越普遍,所以jQuery也提供了getJSON()
方法来快速通过GET获取一个JSON对象:
var jqxhr = $.getJSON('/path/to/resource', { name: 'Bob Lee', check: 1 }).done(function (data) { // data已经被解析为JSON对象了 });
关于跨域:如果需要使用JSONP,可以在ajax()
中设置jsonp: 'callback'
,让jQuery实现JSONP跨域加载数据。
6、扩展
编写jQuery插件
给jQuery对象绑定一个新方法是通过扩展$.fn
对象实现的
$.fn.highlight = function (options) { // 合并默认值和用户设定值: var opts = $.extend({}, $.fn.highlight.defaults, options); this.css('backgroundColor', opts.backgroundColor).css('color', opts.color); return this; } // 设定默认值: $.fn.highlight.defaults = { color: '#d85030', backgroundColor: '#fff8de' }
注意到函数内部的this
在调用时被绑定为jQuery对象,所以函数内部代码可以正常调用所有jQuery对象的方法
为什么最后要return this;
?因为jQuery对象支持链式操作,我们自己写的扩展方法也要能继续链式下去
对于默认值的处理,我们用了一个简单的&&
和||
短路操作符,总能得到一个有效的值
另一种方法是使用jQuery提供的辅助方法$.extend(target, obj1, obj2, ...)
,它把多个object对象的属性合并到第一个target对象中,遇到同名属性,总是使用靠后的对象的值,也就是越往后优先级越高,那默认值放哪比较合适?放全局变量肯定不合适,最佳地点是$.fn.highlight2
这个函数对象本身。
针对特定元素的扩展
$.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); } }); } }); }
最终,我们得出编写一个jQuery插件的原则:
- 给
$.fn
绑定函数,实现插件的代码逻辑; - 插件函数最后要
return this;
以支持链式调用; - 插件函数要有默认值,绑定在
$.fn.<pluginName>.defaults
上; - 用户在调用时可传入设定值以便覆盖默认值。