JQuery基础知识
来源:廖雪峰js教程 https://www.liaoxuefeng.com
jQuery能帮我们干这些事情:
- 消除浏览器差异:你不需要自己写冗长的代码来针对不同的浏览器来绑定事件,编写AJAX等代码;
- 简洁的操作DOM的方法:写$(‘#test’)肯定比document.getElementById(‘test’)来得简洁;
- 轻松实现动画、修改CSS等各种操作。
$符号
\$是著名的jQuery符号。实际上,jQuery把所有功能全部封装在一个全局变量jQuery中,而\$也是一个合法的变量名,它是变量jQuery的别名:
window.jQuery; // jQuery(selector, context)
window.$; // jQuery(selector, context)
$ === jQuery; // true
typeof($); // 'function'
\$本质上就是一个函数,但是函数也是对象,于是\$除了可以直接调用外,也可以有很多其他属性。
选择器
// 按ID查找
var div = $('#abc');
// 按Tag查找
var ps = $('p'); // 返回所有<p>节点
ps.length; // 数一数页面有多少个<p>节点
// 按Class查找
var a = $('.red'); // 所有节点包含`class="red"`都将返回
// 按属性查找
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
// 例如: name="icon-1", name="icon-2"
var names = $('[name$=with]'); // 找出所有name属性值以with结尾的DOM
// 例如: name="startswith", name="endswith"
var icons = $('[class^="icon-"]'); // 找出所有class包含至少一个以`icon-`开头的DOM
// 组合查找
var emailInput = $('input[name=email]');
var tr = $('tr.red'); // 找出<tr class="red ...">...</tr>
// 多项选择器
$('p,div'); // 把<p>和<div>都选出来
$('p.red,p.green'); // 把<p class="red">和<p class="green">都选出来
jQuery的选择器不会返回undefined或者null, 如果无符合的对象,返回的jQuery对象是[]。
jQuery对象和DOM对象之间可以互相转化:
var div = $('#abc'); // jQuery对象
var divDom = div.get(0); // 假设存在div,获取第1个DOM元素
var another = $(divDom); // 重新把DOM包装为jQuery对象
更高级的选择器
<!-- HTML结构 -->
<div class="testing">
<ul class="lang">
<li class="lang-javascript">JavaScript</li>
<li class="lang-python">Python</li>
<li class="lang-lua">Lua</li>
</ul>
</div>
// 层级选择器
$('ul.lang li'); // 选出JavaScript、Python和Lua 3个节点
$('ul.lang li.lang-javascript');
$('div.testing li.lang-javascript');
// 子选择器 $('parent>child')类似层级选择器,但是限定了层级关系必须是父子关系,就是<child>节点必须是<parent>节点的直属子节点。
$('ul.lang>li.lang-javascript'); // 可以选出[<li class="lang-javascript">JavaScript</li>]
$('div.testing>li.lang-javascript'); // [], 无法选出,因为<div>和<li>不构成父子关系
// 过滤器
$('ul.lang li:first-child'); // 仅选出JavaScript
$('ul.lang li:last-child'); // 仅选出Lua
$('ul.lang li:nth-child(2)'); // 选出第N个元素,N从1开始
$('ul.lang li:nth-child(even)'); // 选出序号为偶数的元素
$('ul.lang li:nth-child(odd)'); // 选出序号为奇数的元素
// 查找和过滤
// 用find()从元素中查找
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
// 用parent()向上查找
var swf = $('#swift'); // 获得Swift
var parent = swf.parent(); // 获得Swift的上层节点<ul>
var a = swf.parent('.red'); // 获得Swift的上层节点<ul>,同时传入过滤条件。如果ul不符合条件,返回空jQuery对象
// next()和prev()向后向前查找
var swift = $('#swift');
swift.next(); // Scheme
swift.next('[name=haskell]'); // 空的jQuery对象,因为Swift的下一个元素Scheme不符合条件[name=haskell]
swift.prev(); // Python
swift.prev('.dy'); // Python,因为Python同时符合过滤器条件.dy
// filter()从中过滤
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
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()方法一致
操作DOM
// 修改文本
$('#test-ul li[name=book]').text(); // 'Java & JavaScript'
$('#test-ul li[name=book]').text('修改内容'); // 'Java & JavaScript'
$('#test-ul li[name=book]').html(); // 'Java & JavaScript'
// 修改css
var div = $('#test-div');
div.css('color'); // '#000033', 获取CSS属性
div.css('color', '#336699'); // 设置CSS属性
div.css('color', ''); // 清除CSS属性
// 修改class
var div = $('#test-div');
div.hasClass('highlight'); // false, class是否包含highlight
div.addClass('highlight'); // 添加highlight这个class
div.removeClass('highlight'); // 删除highlight这个class
// 显示和隐藏DOM
var a = $('a[target=_blank]');
a.hide(); // 隐藏
a.show(); // 显示
// 获取DOM信息
// 浏览器可视窗口大小:
$(window).width(); // 800
$(window).height(); // 600
// HTML文档大小:
$(document).width(); // 800
$(document).height(); // 3500
// 某个div的大小:
var div = $('#test-div');
div.width(); // 600
div.height(); // 300
div.width(400); // 设置CSS属性 width: 400px,是否生效要看CSS是否有效
div.height('200px'); // 设置CSS属性 height: 200px,是否生效要看CSS是否有效
// attr()和removeAttr()方法用于操作DOM节点的属性
// <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
// prop()方法和attr()类似,但是HTML5规定有一种属性在DOM节点中可以没有值,只有出现与不出现两种,例如:
// <input id="test-radio" type="radio" name="test" checked value="1">
// 对于checked,使用prop会更好。
// 判断是否被选中
var radio = $('#test-radio');
radio.is(':checked'); // true
var select = $('#test-select');
select.is(':selected')
// 操作表单
// 对于表单元素,jQuery对象统一提供val()方法获取和设置对应的value属性:
input.val(); // 'test' 取值
input.val('abc@example.com'); // 赋值
修改DOM结构
// 添加DOM
ul.append('<li><span>Haskell</span></li>'); // 在ul里面添加li
// 同级节点可以用after()或者before()方法
js.after('<li><span>Lua</span></li>'); // 在js元素后面添加Lua
// 删除节点
$('#test-div>ul>li').remove(); // 所有<li>全被删除
事件
// 获取超链接的jQuery对象:
var a = $('#test-link');
a.on('click', function () {
alert('Hello!');
});
on方法用来绑定一个事件,我们需要传入事件名称和对应的处理函数。
鼠标事件
click: 鼠标单击时触发;
dblclick:鼠标双击时触发;
mouseenter:鼠标进入时触发;
mouseleave:鼠标移出时触发;
mousemove:鼠标在DOM内部移动时触发;
hover:鼠标进入和退出时触发两个函数,相当于mouseenter加上mouseleave。
键盘事件
键盘事件仅作用在当前焦点的DOM上,通常是<input>
和<textarea>
。
keydown:键盘按下时触发;
keyup:键盘松开时触发;
keypress:按一次键后触发。
其他事件
focus:当DOM获得焦点时触发;
blur:当DOM失去焦点时触发;
change:当<input>
、<select>
或<textarea>
的内容改变时触发;
submit:当<form>
提交时触发;
ready:当页面被载入并且DOM树完成初始化后触发。ready仅作用于document对象。
ready方法可以避免js在DOM未加载完毕之前执行相关绑定或方法。所以我们自己的初始化代码必须放到document对象的ready事件中,保证DOM已完成初始化。
// 直接使用ready方法
$(document).ready(function () {
// on('submit', function)也可以简化:
$('#testForm).submit(function () {
alert('submit!');
});
});
// 甚至可以省略ready
$(function () {
// init...
});
可以反复绑定事件处理函数,它们会依次执行
事件参数
// 所有事件都会传入Event对象作为参数,可以从Event对象上获取到更多的信息
$(function () {
$('#testMouseMoveDiv').mousemove(function (e) { // e就是时间参数
$('#testMouseMoveSpan').text('pageX = ' + e.pageX + ', pageY = ' + e.pageY);
});
});
取消绑定
// 一个已被绑定的事件可以解除绑定,通过off('click', function)实现,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!');
});
a.off('click') // 一次性移除已绑定的click事件的所有处理函数
a.off() // 移除所有类型的事件处理函数。
取消绑定可以实现比如拦截表单提交等操作。
form.off().submit(function (e) { // 移除表单所有事件,并绑定新的submit事件
e.preventDefault(); // 通知 Web 浏览器不要执行与事件关联的默认动作
alert(form.serialize()); // 打印表格信息
});
事件触发条件
一个需要注意的问题是,事件的触发总是由用户操作引发的。如果用JavaScript代码去改动文本框的值,将不会触发change事件。
有些时候,我们希望用代码触发change事件,可以直接调用无参数的change()方法来触发该事件:
var input = $('#test-input');
input.val('change it!'); // 通过js修改不会触发change事件
input.change(); // 触发change事件
浏览器安全限制
在浏览器中,有些JavaScript代码只有在用户触发下才能执行,例如,window.open()函数。
var button1 = $('#testPopupButton1');
var button2 = $('#testPopupButton2');
function popupTestWindow() {
window.open('/');
}
button1.click(function () {
popupTestWindow();
});
button2.click(function () {
// 不立刻执行popupTestWindow(),100毫秒后执行:
setTimeout(popupTestWindow, 100);
});
当用户点击button1时,click事件被触发,由于popupTestWindow()在click事件处理函数内执行,这是浏览器允许的,而button2的click事件并未立刻执行popupTestWindow(),延迟执行的popupTestWindow()将被浏览器拦截。
动画
用JavaScript实现动画,原理非常简单:我们只需要以固定的时间间隔(例如,0.1秒),每次把DOM元素的CSS样式修改一点(例如,高宽各增加10%),看起来就像动画了。
// 左上角
div.hide(3000); // 在3秒钟内逐渐消失
div.show('slow'); // 在0.6秒钟内逐渐显示
div.toggle('slow') // 根据当前状态决定是show()还是hide()。
// 垂直方向
div.slideUp(3000); // 在3秒钟内逐渐向上消失
div.slideDown('slow')
div.slideToggle('slow')
// 淡入淡出
div.fadeOut('slow')
div.fadeIn('slow')
div.fadeToggle('slow')
自定义动画
animate()可以实现任意动画效果,我们需要传入的参数就是DOM元素最终的CSS状态和时间,jQuery在时间段内不断调整CSS直到达到我们设定的值。
var div = $('#test-animate');
div.animate({
opacity: 0.25,
width: '256px',
height: '256px'
}, 3000); // 在3秒钟内CSS过渡到设定值
// animate()还可以再传入一个函数,当动画结束时,该函数将被调用
var div = $('#test-animate');
div.animate({
opacity: 0.25,
width: '256px',
height: '256px'
}, 3000, function () {
console.log('动画已结束');
// 恢复至初始状态:
$(this).css('opacity', '1.0').css('width', '128px').css('height', '128px');
});
串行动画
jQuery的动画效果还可以串行执行,通过delay()方法还可以实现暂停,这样,我们可以实现更复杂的动画效果,而代码却相当简单。
var div = $('#test-animates');
// 动画效果:slideDown - 暂停 - 放大 - 暂停 - 缩小
div.slideDown(2000)
.delay(1000)
.animate({
width: '256px',
height: '256px'
}, 2000)
.delay(1000) // 延迟1秒
.animate({
width: '128px',
height: '128px'
}, 2000);
}
停止动画
$("#stop").click(function(){
$("#panel").stop();
});
语法: $(selector).stop(stopAll,goToEnd);
可选的 stopAll 参数规定是否应该清除动画队列。默认是 false,即仅停止活动的动画,允许任何排入队列的动画向后执行。可选的 goToEnd 参数规定是否立即完成当前动画。默认是 false。因此,默认地,stop() 会清除在被选元素上指定的当前动画。