跳转到内容
新建笔记

jQuery

JavaScript世界中使用最广泛的一个库,jQuery的理念“Write Less, Do More“,让你写更少的代码,完成更多的工作。jQuery能帮我们干这些事情:

  • 消除浏览器差异:你不需要自己写冗长的代码来针对不同的浏览器来绑定事件,编写AJAX等代码;
  • 简洁的操作DOM的方法:写$('#test')肯定比document.getElementById('test')来得简洁;
  • 轻松实现动画、修改CSS等各种操作。
// 使用
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
...
</head>
<body>
...
</body>
</html>

$是著名的jQuery符号。实际上,jQuery把所有功能全部封装在一个全局变量jQuery中,而$也是一个合法的变量名,它是变量jQuery的别名:

window.jQuery; // jQuery(selector, context)
window.$; // jQuery(selector, context)
$ === jQuery; // true
typeof($); // 'function'

$本质上就是一个函数,但是函数也是对象,于是$除了可以直接调用外,也可以有很多其他属性。注意,你看到的$函数名可能不是jQuery(selector, context),因为很多JavaScript压缩工具可以对函数名和参数改名,所以压缩过的jQuery源码$函数可能变成a(b,c)。绝大多数时候,我们都直接用$(因为写起来更简单嘛)。但是,如果$这个变量不幸地被占用了,而且还不能改,那我们就只能让jQuery把$变量交出来,然后就只能使用jQuery这个变量:

// 原理是jQuery在占用$之前,先在内部保存了原来的$,调用jQuery.noConflict()时会把原来保存的变量还原。
$; // jQuery(selector, context)
jQuery.noConflict();
$; // undefined
jQuery; // jQuery(selector, context)

选择器是jQuery的核心。一个选择器写出来类似$('#dom-id')。

为什么jQuery要发明选择器?jQuery的选择器就是帮助我们快速定位到一个或多个DOM节点。回顾一下DOM操作中我们经常使用的代码:

// 按ID查找:
let a = document.getElementById('dom-id');
// 按tag查找:
let divs = document.getElementsByTagName('div');
// 查找<p class="red">:
let ps = document.getElementsByTagName('p');
// 过滤出class="red":
// TODO:
// 查找<table class="green">里面的所有<tr>:
let table = ...
for (let i=0; i<table.children; i++) {
// TODO: 过滤出<tr>
}

这些代码实在太繁琐了,并且,在层级关系中,例如,查找<table class="green">里面的所有<tr>,一层循环实际上是错的,因为<table>的标准写法是:

<table>
<tbody>
<tr>...</tr>
<tr>...</tr>
</tbody>
</table>

什么是jQuery对象?jQuery对象类似数组,它的每个元素都是一个引用了DOM节点的对象。

// 按ID查找
// 查找<div id="abc"> ,#abc以#开头。返回的对象是jQuery对象。
let div = $('#abc');
// 返回
[<div id="abc">...</div>]
// 如果id为abc的<div>不存在,返回的jQuery对象如下:
[]
// jQuery对象和DOM对象之间可以互相转化:
let div = $('#abc'); // jQuery对象
let divDom = div.get(0); // 假设存在div,获取第1个DOM元素
let another = $(divDom); // 重新把DOM包装为jQuery对象
查找方式选择器语法详细说明代码示例
按ID查找#id通过元素的 id 属性查找,使用 # 号开头。返回的 jQuery 对象类似数组。let div = $('#abc');
按Tag查找tag通过元素的 tag 名称查找。可以获取页面中所有指定的标签元素。let ps = $('p');
按Class查找.class通过元素的 class 属性查找,使用 . 号开头。可以查找包含特定 class 的所有元素。let a = $('.red');
按属性查找[attribute=value]按照指定属性及其值查找元素。适用于查找特定属性的元素。let email = $('[name=email]');
按属性前缀查找[attribute^=prefix]查找指定属性的值以给定前缀开头的元素。let icons = $('[name^=icon]');
按属性后缀查找[attribute$=suffix]查找指定属性的值以给定后缀结尾的元素。let names = $('[name$=with]');
组合查找tag.class, tag[attribute]结合 tag、class 或 attribute 等多种选择器组合进行查找。let emailInput = $('input[name=email]');
多项选择器selector1, selector2, ...多个选择器通过 , 号分隔来组合查找。返回的元素是按照它们在 HTML 中出现的顺序排列的。$('p.red,p.green');
// 按ID查找
let div = $('#abc');
// 按Tag查找
let ps = $('p');
// 按Class查找
let a = $('.red');
// 按属性查找
let email = $('[name=email]');
// 按属性前缀查找
let icons = $('[name^=icon]');
// 按属性后缀查找
let names = $('[name$=with]');
// 组合查找
let emailInput = $('input[name=email]');
// 多项选择器
$('p.red,p.green');
选择器类型说明jQuery代码示例
层级选择器根据层级关系选择元素,使用空格分隔。$('ancestor descendant');
选择
    元素下的所有
  • 元素。
$('ul.lang li');
选择
元素下的所有
  • 元素。
  • $('div.testing li');
    子选择器选择直接子元素,使用>分隔。$('parent>child');
    选择
      元素的直接
    • 子元素。
    $('ul.lang>li');
    过滤器附加在选择器上,帮助更精确地定位元素。$('ul.lang li:first-child');
    选择第一个
  • 元素。
  • $('ul.lang li:first-child');
    表单相关选择器选择特定类型的表单元素。:input, :file, :checkbox, :radio, :focus, :checked, :enabled, :disabled
    可见/隐藏选择器选择可见或隐藏的元素。$('div:visible');, $('div:hidden');
    查找在jQuery对象的子节点中查找,使用find()方法。ul.find('.dy');
    上查找从当前节点向上查找,使用parent()方法。$('#swift').parent();
    相邻节点查找查找相邻的同级节点,使用next()和prev()方法。$('#swift').next();, $('#swift').prev('.dy');
    过滤过滤掉不符合条件节点,使用filter()方法。langs.filter('.dy');
    函数过滤传入函数进行过滤,this绑定为DOM对象。langs.filter(function () { return this.innerHTML.indexOf('S') === 0; });
    映射将jQuery对象的DOM节点转化为其他对象,使用map()方法。langs.map(function () { return this.innerHTML; }).get();
    首/尾节点选择返回jQuery对象的第一个或最后一个节点,使用first()和last()方法。langs.first();, langs.last();
    切片选择返回jQuery对象的子集,使用slice()方法。langs.slice(2, 4);
    <!-- HTML结构 -->
    <ul id="test-ul">
    <li class="js">JavaScript</li>
    <li name="book">Java &amp; JavaScript</li>
    </ul>
    $('#test-ul li[name=book]').text(); // 'Java & JavaScript'
    $('#test-ul li[name=book]').html(); // 'Java &amp; JavaScript'
    // jQuery的API设计非常巧妙:无参数调用text()是获取文本,传入参数就变成设置文本,HTML也是类似操作
    let j1 = $('#test-ul li.js');
    let j2 = $('#test-ul li[name=book]');
    j1.html('<span style="color: #c00">JavaScript</span>');
    j2.text('JavaScript & ECMAScript');
    $('#test-ul li').text('JS'); // 是不是两个节点都变成了JS?
    // 如果不存在id为not-exist的节点:
    $('#not-exist').text('Hello'); // 代码不报错,没有节点被设置为'Hello'

    修改css

    <!-- HTML结构 -->
    <ul id="test-css">
    <li class="lang dy"><span>JavaScript</span></li>
    <li class="lang"><span>Java</span></li>
    <li class="lang dy"><span>Python</span></li>
    <li class="lang"><span>Swift</span></li>
    <li class="lang dy"><span>Scheme</span></li>
    </ul>
    $('#test-css li.dy>span').css('background-color', '#ff0').css('color', '#c00');
    // 注意,jQuery对象的所有方法都返回一个jQuery对象(可能是新的也可能是自身),这样我们可以进行链式调用,非常方便。
    let div = $('#test-div');
    div.css('color'); // '#000033', 获取CSS属性
    div.css('color', '#336699'); // 设置CSS属性
    div.css('color', ''); // 清除CSS属性
    // css()方法将作用于DOM节点的style属性,具有最高优先级。如果要修改class属性,可以用jQuery提供的下列方法
    let div = $('#test-div');
    div.hasClass('highlight'); // false, class是否包含highlight
    div.addClass('highlight'); // 添加highlight这个class
    div.removeClass('highlight'); // 删除highlight这个class

    修改DOM结构

    <div id="test-div">
    <ul>
    <li><span>JavaScript</span></li>
    <li><span>Python</span></li>
    <li><span>Swift</span></li>
    </ul>
    </div>
    let ul = $('#test-div>ul');
    ul.append('<li><span>Haskell</span></li>'); //调用append()传入HTML片段
    // append()还可以传入原始的DOM对象,jQuery对象和函数对象
    // 创建DOM对象:
    let 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>';
    });
    // 如果要把新节点插入到指定位置,可以先定位到JavaScript,然后用after()方法:
    let js = $('#test-div>ul>li:first-child');
    js.after('<li><span>Lua</span></li>');
    // 要删除DOM节点,拿到jQuery对象后直接调用remove()方法就可以了。如果jQuery对象包含若干DOM节点,实际上可以一次删除多个DOM节点
    let li = $('#test-div>ul>li');
    li.remove(); // 所有<li>全被删除

    因为JavaScript在浏览器中以单线程模式运行,页面加载后,一旦页面上所有的JavaScript代码被执行完后,就只能依赖触发事件来执行JavaScript代码。浏览器在接收到用户的鼠标或键盘输入后,会自动在对应的DOM节点上触发相应的事件。如果该节点已经绑定了对应的JavaScript处理函数,该函数就会自动调用。由于不同的浏览器绑定事件的代码都不太一样,所以用jQuery来写代码,就屏蔽了不同浏览器的差异,我们总是编写相同的代码。

    /* HTML:
    *
    * <a id="test-link" href="#0">点我试试</a>
    *
    */
    // 获取超链接的jQuery对象:
    let a = $('#test-link');
    a.on('click', function () { // on方法用来绑定一个事件,我们需要传入事件名称和对应的处理函数。
    alert('Hello!');
    });
    // 更简化的写法是直接调用click()方法:
    a.click(function () {
    alert('Hello!');
    });
    // 有些事件,如mousemove和keypress,我们需要获取鼠标位置和按键的值,否则监听这些事件就没什么意义了。所有事件都会传入Event对象作为参数,可以从Event对象上获取到更多的信息
    $(function () {
    $('#testMouseMoveDiv').mousemove(function (e) {
    $('#testMouseMoveSpan').text('pageX = ' + e.pageX + ', pageY = ' + e.pageY);
    });
    });
    // 一个已被绑定的事件可以解除绑定,通过off('click', function)实现:
    unction hello() {
    alert('hello!');
    }
    a.click(hello); // 绑定事件
    // 10秒钟后解除绑定:
    setTimeout(function () {
    a.off('click', hello);
    }, 10000);
    // 一个需要注意的问题是,事件的触发总是由用户操作引发的。例如,我们监控文本框的内容改动:
    let input = $('#test-input');
    input.change(function () {
    console.log('changed...');
    });
    // 当用户在文本框中输入时,就会触发change事件。但是,如果用JavaScript代码去改动文本框的值,将不会触发change事件:
    let input = $('#test-input');
    input.val('change it!'); // 无法触发change事件
    // 有些时候,我们希望用代码触发change事件,可以直接调用无参数的change()方法来触发该事件:
    let input = $('#test-input');
    input.val('change it!');
    input.change(); // 触发change事件
    事件类型说明jQuery代码示例
    click鼠标单击时触发。$('#myButton').click(function() { alert('Clicked!'); });
    dblclick鼠标双击时触发。$('#myElement').dblclick(function() { alert('Double clicked!'); });
    mouseenter鼠标进入元素时触发。$('#myElement').mouseenter(function() { alert('Mouse entered!'); });
    mouseleave鼠标离开元素时触发。$('#myElement').mouseleave(function() { alert('Mouse left!'); });
    mousemove鼠标在元素内部移动时触发。$('#myElement').mousemove(function() { alert('Mouse moving!'); });
    hover鼠标进入和退出元素时分别触发两个函数。$('#myElement').hover( function() { alert('Mouse entered!'); }, function() { alert('Mouse left!'); } );
    keydown键盘按键被按下时触发(作用于获得焦点的DOM)。$('#myInput').keydown(function() { alert('Key down!'); });
    keyup键盘按键被松开时触发(作用于获得焦点的DOM)。$('#myInput').keyup(function() { alert('Key up!'); });
    keypress每次按键时触发(作用于获得焦点的DOM)。$('#myInput').keypress(function() { alert('Key pressed!'); });
    focus元素获得焦点时触发。$('#myInput').focus(function() { alert('Element focused!'); });
    blur元素失去焦点时触发。$('#myInput').blur(function() { alert('Element blurred!'); });
    change输入字段、选择框或文本域的值改变时触发。$('#myInput').change(function() { alert('Value changed!'); });
    submit表单提交时触发。$('#myForm').submit(function() { alert('Form submitted!'); });
    ready页面DOM树完成初始化后触发,适合写初始化代码。$(document).ready(function() { alert('DOM ready!'); });
    事件类型说明jQuery代码示例
    鼠标事件包括点击、双击、鼠标移动等事件。$('#test-link').on('click', function () { alert('Hello!'); });
    键盘事件作用在获得焦点的DOM上,如<input>和<textarea>。$('#test-input').on('keydown', function () { console.log('Key down'); });
    其他事件如焦点、内容改变、表单提交等。$('#testForm').on('submit', function () { alert('Form submitted!'); });
    ready事件当页面DOM树完成初始化后触发,适合写初始化代码。$(document).ready(function () { // Initialization code });
    事件参数事件处理函数可以访问Event对象,获取更多事件信息。$('#testMouseMoveDiv').on('mousemove', function (e) { console.log(e.pageX, e.pageY); });
    取消绑定移除已绑定的事件处理函数。$('#test-link').off('click', function () { alert('Hello!'); });
    事件触发条件事件通常由用户操作触发,但也可以手动触发。$('#test-input').val('change it!').trigger('change');

    用JavaScript实现动画,原理非常简单:我们只需要以固定的时间间隔(例如,0.1秒),每次把DOM元素的CSS样式修改一点(例如,高宽各增加10%),看起来就像动画了。但是要用JavaScript手动实现动画效果,需要编写非常复杂的代码。如果想要把动画效果用函数封装起来便于复用,那考虑的事情就更多了。使用jQuery实现动画,代码已经简单得不能再简化了:只需要一行代码!

    动画类型说明jQuery代码示例
    show / hide显示或隐藏元素,可以带时间参数实现动画效果。$('#test-show-hide').show('slow');
    toggle根据当前状态决定是显示还是隐藏,也可以带时间参数。$('#test-toggle').toggle('slow');
    slideUp / slideDown垂直方向展开或收起元素,可以带时间参数实现动画效果。$('#test-slide').slideUp('slow');
    slideToggle根据元素是否可见来决定slideUp或slideDown。$('#test-slide-toggle').slideToggle('slow');
    fadeIn / fadeOut淡入淡出效果,通过设置opacity属性实现。$('#test-fade').fadeIn('slow');
    fadeToggle根据元素是否可见来决定fadeIn或fadeOut。$('#test-fade-toggle').fadeToggle('slow');
    animate自定义动画效果,通过改变CSS属性实现。$('#test-animate').animate({opacity: 0.25, width: '256px', height: '256px'}, 3000);
    串行动画通过delay实现动画效果的串行执行和暂停。$('#test-animates').slideDown(2000).delay(1000).animate({width: '256px', height: '256px'}, 2000);