FreezeJ' Blog

JQuery基础知识

2019-04-28

JQuery基础知识

来源:廖雪峰js教程 https://www.liaoxuefeng.com

jQuery能帮我们干这些事情:

  1. 消除浏览器差异:你不需要自己写冗长的代码来针对不同的浏览器来绑定事件,编写AJAX等代码;
  2. 简洁的操作DOM的方法:写$(‘#test’)肯定比document.getElementById(‘test’)来得简洁;
  3. 轻松实现动画、修改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 &amp; 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() 会清除在被选元素上指定的当前动画。

Tags: JQuery