Skip to content

jQuery 简化 JS 操作

第一章:初识 jQuery

一、概念

百度百科

jQuery 是继 Prototype 之后又一个优秀的 JavaScript 代码库。jQuery 设计的宗旨是“write Less,Do More”,即倡导写更少的代码,做更多的事情。它封装 JavaScript 常用的功能代码,提供一种简便的 JavaScript 设计模式,优化 HTML 文档操作、事件处理、动画设计和 Ajax 交互。

简单解释

一个 JavaScript 库。简化 JS 开发。

目前地位

目前 jQuery 已经进入维护模式。各大网站也在移除对 jQuery 的依赖,如 Bootstrap、GitHub …… 但因为 jQuery 使用广泛,或许在今后的工作中需要维护旧的网站,可能会使用到。同时它依旧是优秀的 JS 库,因此应当学习 jQuery。

如果项目采用 MVVM 框架进行开发,建议也不要引入 jQuery。就算需要通过 JS 来操作 DOM,也应当使用原生 JS API。

二、文档

官网

https://jquery.com

源码下载

官网下载:https://jquery.com/download/

CDN 连接地址下载:https://releases.jquery.com/jquery/

GitHub 仓库中下载:https://github.com/jquery/jquery

三、版本

版本

1.x:兼容 ie678。使用最为广泛的,官方只做 BUG 维护。

    功能不再新增。因此一般项目来说,使用 1.x 版本就可以了。

    最终版本:1.12.4 ( 2016 年 5 月 20 日)

2.x:不兼容 ie678,很少有人使用,官方只做 BUG 维护。

    功能不再新增。如果不考虑兼容低版本的浏览器可以使用 2.x。

    最终版本:2.2.4 ( 2016 年 5 月 20 日)

3.x:不兼容 ie678,只支持最新的浏览器。除非特殊要求,一般不会使用 3.x 版本的,很多老的 jQuery 插件不支持这个版本。

……

jQuery 生态系统

jQuery Core (核心库):学习的这个。

jQuery UI:用户界面组件库。处于仅维护模式。

jQuery Mobile:一个触摸优化的 HTML5 UI 框架,旨在使响应式网站和应用程序可在所有智能手机、平板电脑和桌面设备上访问。已弃用。

……

文件区别

jquery-xxx.js:开发版本。给程序员看的,有良好的缩进和注释。体积大一些。

jquery-xxx.min.js:生产版本。程序中使用,没有缩进。体积小一些。程序加载更快。


uncompressed:完整未压缩。

minified:完整压缩。

slim:精简未压缩。移除 Ajax 和 effects (特效) 模块。只用于操作 DOM 场景。

slim minified:精简压缩。功能同上,只是进行了压缩。

第二章:jQuery 基础

一、基本操作

1. 监听 DOMContentLoaded 事件

DOM 树渲染完毕执行回调。

javascript
// 方式 1: 监听文档完全解析完成
var $doc = $(document)
$doc.ready(function() {
  console.log('doc ready')
})

// 方式 2: 监听文档完全解析完成
jQuery('document').ready(function(){
  console.log('doc ready')
})

// 方式 3: 监听文档完全解析完成
$().ready(function(){
  console.log('doc ready')
})

// 方式 4: 监听文档完全解析完成【推荐】
$(function() {
  console.log('doc ready')
})

2. 监听 window load 事件

监听整个 HTML 页面加载完成(外部链接和图片资源等)执行回调。

javascript
// 方法一
$(window).load(function() {}) // 3.0 版本 remove

// 方法二【推荐】
$(window).on('load', function() {
  console.log('图片加载完成')
})

window.onload = function() {};:只能定义一次,如果定义多次,后边的会将前边的覆盖掉。

window.addEventListener('load', function() {});:可以定义多次,不会覆盖。

window.addEventListener('DOMContentLoaded', function() {});:可以定义多次,不会覆盖。

$(window).on('load', function() {})$(function):可以定义多次,不会覆盖。

3. jQuery 与其它库的变量名冲突

和 jQuery 库一样,许多 JavaScript 库也会使用 $ 作为函数名或变量名。在 jQuery 中,$ 是 jQuery 的别名。

如果我们在使用 jQuery 库之前,其它库已经使用了 $ 函数或者变量,这时就会出现冲突的情况。我们可以通过调用 jQuery 中的 noConflict 函数来解决冲突问题。jQuery 会在初始化前会先备份一下全局其它库的 jQuery 和 $ 变量,调用 noConflict 函数只是恢复之前备份的 jQuery 和 $ 变量。

javascript
// jQuery 源码
var

  // Map over jQuery in case of overwrite
  _jQuery = window.jQuery, // 先备份其它框架的jQuery变量

  // Map over the $ in case of overwrite
  _$ = window.$; // 先备份其它框架的$变量

jQuery.noConflict = function( deep ) {
  if ( window.$ === jQuery ) { // 判断当前的$是否是jQuery
    window.$ = _$; // 恢复先前备份其它框架的$
  }

  if ( deep && window.jQuery === jQuery ) {
    window.jQuery = _jQuery; // 恢复先前备份其它框架的jQuery
  }

  return jQuery; // 返回 jQuery 函数
};

// 将jQuery暴露为全局变量
if ( typeof noGlobal === "undefined" ) {
  window.jQuery = window.$ = jQuery;
}

代码解释:

  • noConflict 方法主要用于释放先前备份好的其他库的 $ 和 jQuery。
  • 如果调用 noConflict 方法时传递了 deep 参数为真,那么不仅 $ 变量会被恢复,jQuery 变量也会被恢复。
  • 通过返回 jQuery 对象,允许开发者在调用 noConflict 方法后,仍然可以通过变量来使用 jQuery。

二、jQ 函数与 jQ 对象

1. jQ 函数

jQuery 是一个工厂函数(别名 $)。调用该函数,会根据传入参数类型来返回匹配到的元素集合,一般把该集合称为 jQuery 对象。

  • 如果传入假值:返回一个空的集合。
  • 如果传入选择器:返回在 documnet 中所匹配到元素的集合。
  • 如果传入元素类型:返回包含该元素的集合(把 js 对象转为了 jQuery 对象)。
  • 如果传入 HTML 字符串,返回包含新创建元素的集合。
  • 如果传入回调函数:返回的是包含 document 元素集合,并且当文档加载完成会回调该函数。

因为函数也是对象,所以该函数还包含了很多已封装好的方法。如:jQuery.noConflictjQuery.ready 等,相当于类方法。

下面是例子。

  • jQuery( selector [, context ] ) :selector 是字符串选择器;context 是匹配元素时的上下文,默认值为 document。

  • jQuery( element ) :将原生的 JavaScript DOM 元素包装成 jQuery 对象。

    jQuery( elementArray )

  • jQuery() :不传入任何参数,会返回一个空的 jQuery 对象。不过,可以在这个对象上调用例如 .push() 等一些数组方法,因为 jQuery 对象本质上是一个类似数组的对象。

  • jQuery( html [, ownerDocument ] ) :根据给定的 HTML 字符串创建新的 jQuery 对象。

    jQuery( html )

  • jQuery( callback )

2. jQ 对象

jQuery 对象是通过调用 jQuery 函数来创建的。jQuery 对象是一个包含所匹配到元素的集合,该集合是类数组(array-like)对象。

  • jQuery 对象中会包含 N(>=0)个匹配到的元素。
  • jQuery 对象原型中包含了很多已封装好的方法。例如:DOM操作、事件处理、动画等方法。

下面我们通过调用 jQuery 函数来新建一个 jQuery 对象,例如:$(document) 会新建一个包含 document 元素的 jQuery 对象。

jQuery 对象和 JS 对象区别与转换

jQuery 对象在操作时,更加方便。但是,jQuery 对象和 js 对象方法不通用的。那么就需要两者相互转换。

jq --> js : jq对象[索引] 或者 jq对象.get(索引)

  • 如果 index 超出范围(小于负数元素或等于或大于元素数),则返回 undefined。
  • .get() : 没有参数,将返回 jQuery 对象中所有 DOM 元素的数组。

js --> jq : 调用 jQuery 函数或者 $ 函数。例如:$(js对象)

三、jQ 架构设计图

javascript
// 立即执行函数(避免与全局变量冲突)
;(function(global, factory) {
  factory(global)
})(window, function(window) {

  function XQjQuery(selector) {
    // 返回 jQ 对象
    return new XQjQuery.fn.init(selector)
  }

  // 原型方法(实例方法) === 学习这里的类方法
  XQjQuery.prototype = {
    constructor: XQjQuery,
    extend: function() {},
    text: function() {},
    ready: function() {}
  }
  
  // 类方法 === 学习这里的类方法
  XQjQuery.noConflict = function() {}
  XQjQuery.isArray = function() {}
  XQjQuery.map = function() {}

  XQjQuery.fn = XQjQuery.prototype

  // 构造函数(创建jQuery对象)
  XQjQuery.fn.init = function(selector) { // css selector
    
    if(!selector){
      return this
    }
    // 拿到DOM Element源码
    var el = document.querySelector(selector)
    this[0] = el
    this.length = 1
    return this
  }

  XQjQuery.fn.init.prototype = XQjQuery.fn

  window.XQjQuery = window.$ = XQjQuery

})

注意:jQuery.fn 是 jQuery 的一个重要部分,它实际上是 jQuery.prototype 的一个别名。该属性用于向所有的 jQuery 实例添加新的特性和方法(扩展功能、插件)。

四、选择器

1. 基本选择器

(1) 标签选择器(元素选择器)

获得所有匹配标签名称的元素。

语法:$("html标签名")

(2) id 选择器

获得与指定 id 属性值匹配的元素。

语法:$("#id的属性值")

(3) 类选择器(样式选择器)

获得与指定的 class 属性值匹配的元素。

语法:$(".class的属性值")

(4) 并集选择器

获取多个选择器选中的所有元素。

语法: $("选择器1, 选择器2....")

(5) 交集选择器

语法:$("选择器1选择器2")

(6) 全集选择器

获取所有元素。

语法:$("*")

2. 层级选择器

(1) 后代选择器

选择 A 元素内部的所有 B 元素(孙子辈的也选)。

语法:$("A B")

(2) 子选择器

选择 A 元素内部的所有 B 子元素。

语法:$("A > B")

(3) 紧邻元素选择器

语法:$("A + B")

(4) 兄弟元素选择器

语法:$("A ~ B")

注:‘+’ 选择器表示某元素后相邻的兄弟元素,也就是紧挨着的,是单个的。而 ‘~’ 选择器则表示某元素后所有同级的指定元素,强调所有的。

3. 属性选择器

(1) 属性名称选择器

包含指定属性的选择器。

语法:$("[属性名]")

(2) 属性选择器

语法:$("A[属性名='值']") 包含指定属性等于指定值的选择器。

          $("A[属性名!='值']") 匹配所有不包含指定的属性,或属性不等于属性值。

          $("A[属性名^='值']") 匹配属性值以 xxx 开头。

          $("A[属性名$='值']") 匹配属性值以 xxx 结尾。

          $("A[属性名*='值']") 匹配属性值有 xxx。

(3) 复合属性选择器

语法:$("A[属性名='值'][]...") 包含多个属性条件的选择器。

4. 过滤选择器

1)基本过滤选择器 / 扩展选择器 *

备注:jQuery 支持 CSS 的结构伪类选择器。

(1) 首元素选择器

获得选择的元素中的第一个元素。

语法::first

(2) 尾元素选择器

获得选择的元素中的最后一个元素。

语法::last

(3) 非元素选择器

不包括指定内容的元素。

语法::not(selector)

例子:

html
<body>
  <h1 class="nt">我是 h1 标签</h1>
  <h4>我是 h4 标签</h4>

  <div class="nt">我是 div 标签,有 nt 类选择器</div>
  <div>我是 div 标签,没有 nt 类选择器</div>
</body>

<script>
  // 选择 h1~h6 元素属性 class 没有 nt 类选择器的元素
  $(":header:not(.nt)").css("backgroundColor","pink");
  // 选择 div 元素属性 class 没有 nt 类选择器的元素
  $("div:not(.nt)").css("backgroundColor","pink");
</script>

(4) 偶数选择器

语法::even 偶数,从 0 开始计数。

(5) 奇数选择器

语法::odd 奇数,从 0 开始计数。

(6) 等于索引选择器

指定索引元素。

语法::eq(index)

(7) 大于索引选择器

大于指定索引元素。

语法::gt(index)

(8) 小于索引选择器

小于指定索引元素。

语法::lt(index)

(9) 标题选择器

获得标题(h1 ~ h6)元素,固定写法。

语法::header

例子:改变标题背景色为粉红。$(":header").css("backgroundColor","pink")

2)内容过滤选择器
语法解锁
:contains(string)选择含有指定文本内容的元素。
:has(selector)选择含有 selector 所匹配的元素。
:empty选择不包含子元素或文本元素的标签。
:parent选择含有子元素或文本元素的标签。是 :empty 的取反。

注意::parent.parent() 是不同的。.parent() 是一个函数,它会选择当前元素的直接父元素,而 :parent 是一个选择器,用于选择那些不是空元素的元素。

javascript
$('div.someClass:contains("Hello")') // 选择所有包含文本 "Hello" 并且有类名 "someClass" 的 div 元素
$('div.someClass:empty') // 选择所有没有子元素并且有类名 "someClass" 的 div 元素
$('div.someClass:has(p)') // 选择所有包含 `<p>` 元素并且有类名 "someClass" 的 div 元素
$('div.someClass:parent') // 选择所有有子元素并且有类名 "someClass" 的 div 元素
3)可见性过滤选择器
语法解释
:hidden匹配所有不可见元素(如:display:none),或者 type (主要指 input 标签) 为 hidden 的元素。
:visible匹配所有可见元素。
4)状态过滤选择器 / 表单过滤选择器 *

(1) 可用元素选择器

获得可用元素。

语法::enabled

javascript
// 利用 jQuery 对象的 val() 方法改变表单内可用 <input> 元素的值
// <input type="text" value="可用值1">
$("input[type='text']:enabled").val("aaa");

(2) 不可用元素选择器

获得不可用元素。

语法::disabled

javascript
// 利用 jQuery 对象的 val() 方法改变表单内不可用 <input> 元素的值
// <input type="text" value="不可用值1" disabled="disabled">
$("input[type='text']:disabled").val("aaa");

(3) 选中选择器

获得单选 / 复选框选中的元素。

语法::checked

javascript
// 利用 jQuery 对象的 length 属性获取复选框选中的个数
alert($("input[type='checkbox']:checked").length);

(4) 选中选择器

获得下拉框选中的元素。

语法::selected

javascript
// 利用 jQuery 对象的 length 属性获取下拉框选中的个数
alert($("#mySelect > option:selected").length);

jQ 过滤器 (Filtering) API

jQuery 过滤器 API(即 jQuery 原型上的方法)。

  • .eq(index) :从匹配元素的集合中,取索引处的元素,eq 全称 equal(等于),返回 jQuery 对象。

  • .first() :从匹配元素的集合中,取第一个元素,返回 jQuery 对象。

  • .last() :从匹配元素的集合中,取最后一个元素,返回 jQuery 对象。

  • .not(selector) :从匹配元素的集合中,删除匹配的元素,返回 jQuery 对象。

  • .filter(selector) :从匹配元素的集合中,过滤出匹配的元素,返回 jQuery 对象。

    html
    <ul>
      <li>list item 1</li>
      <li>list item 2</li>   <!-- 找到这个 -->
      <li>list item 3</li>
      <li>list item 4</li>   <!-- 找到这个 -->
      <li>list item 5</li>
      <li>list item 6</li>   <!-- 找到这个 -->
    </ul>
    
    <script>
      $( "li" ).filter( ":nth-child(2n)" ).css( "background-color", "red" );
    </script>
  • .find(selector) :从匹配元素集合中,找到匹配的后代元素,返回 jQuery 对象。

    html
    <ul class="level-1">
      <li class="item-i">I</li>
      <li class="item-ii">II
        <ul class="level-2">
          <li class="item-a">A</li>       <!-- 找到这个 -->
          <li class="item-b">B            <!-- 找到这个 -->
            <ul class="level-3">
              <li class="item-1">1</li>   <!-- 找到这个 -->
              <li class="item-2">2</li>   <!-- 找到这个 -->
              <li class="item-3">3</li>   <!-- 找到这个 -->
            </ul>
          </li>
          <li class="item-c">C</li>       <!-- 找到这个 -->
        </ul>
      </li>
      <li class="item-iii">III</li>
    </ul>
    
    <script>
      $( "li.item-ii" ).find( "li" ).css( "background-color", "red" );
    </script>
  • .is(selector|element| ... ) :根据选择器、元素等检查当前匹配到元素的集合。集合中至少有一个与给定参数匹配则返回 true。

    html
    <ul>
      <li>list <strong>item 1</strong></li>
      <li><span>list item 2</span></li>
      <li>list item 3</li>
    </ul>
    
    <script>
      $( "ul" ).on( "click", function( event ) {
        var target = $( event.target );
        if ( target.is( "li" ) ) {
          target.css( "background-color", "red" );
        }
      });
    </script>
  • .odd() :将匹配到元素的集合减少为集合中的奇数,从零开始编号,返回 jQuery 对象。

  • .even():将匹配到元素的集合减少到集合中的偶数,从零开始编号,返回 jQuery 对象。

jQuery 中大多数方法都支持链式调用。

五、DOM 操作

1. 文本的操作

html() :获取 / 设置元素的标签体内容。如果 $() 选中了多个元素,那么,只会返回第一个匹配元素的内容。

html
<ul id="list" class="panel">
  <li class="li-1">li-1</li>
  <li class="li-2">li-2</li>
  <li class="li-3">li-3</li>
  <li class="li-4">li-4</li>
  <li class="li-5">li-5</li>
</ul>

<script>
  // 拿到匹配元素集合中的第一个元素 (获取的时候, 一般是拿到匹配元素集合中的第一个元素的数据)
  console.log( $('ul li').html() ) // li-1
</script>

text() :获取 / 设置元素的标签体纯文本内容。如果 $() 选中了多个元素,那么,获取匹配元素集合中内容。

html
<ul>
  <li class="li-1">li-1</li>
  <li class="li-2">li-2</li>
  <li class="li-3">li-3</li>
  <li class="li-4">li-4</li>
  <li class="li-5">li-5
    <span>我是span</span>
  </li>
</ul>

<script>
  console.log( $('ul li').text() )  /*
                                       li-1li-2li-3li-4li-5
                                             我是span
                                    */
</script>

val() :获取 / 设置元素的 value 属性值。主要用于获取 input, select 等表单元素的值。

2. 样式操作

.width()、.width(value):获取匹配到元素集合中第一个元素的宽度或设置每个匹配到元素的宽度。

innerWidth()、innerWidth(value)

outerWidth()、outerWidth(value)

.height()、.height(value):获取匹配到元素集合中第一个元素的高度或设置每个匹配到元素的高度。

innerHeight()、innerHeight(value)

outerHeight()、outerHeight(value)

javascript
// width: content;innerWidth: padding + content;outerWidth: border + padding + content
$('div').width(); // 返回数值型 250
$('div').width(500); // 设置宽度为 500px
$('div').width("50vw");  // 设置宽度为 50vw

.css():当使用 .css() 来获取样式值时,如果选择器匹配多个元素,它只会返回第一个匹配元素的样式值。

javascript
// 获取某个 css 属性值
// .css(propertyName)
$('select').css('width'); // 返回值带单位,字符串类型
// 获取多个 css 属性值
// .css(propertyNames)
$('select').css(['width', 'height']); // 返回的是对象 {width: '223px', height: '105px'}

// 设置某个 css 属性值
// .css(propertyName, value)
$('select').css('width', 500);
$('select').css('width', '500px');
// 设置多个 css 属性值
// .css(properties)
$('select').css({
    width: 500,
    height:500
});

Class 属性的操作

  • .addClass(className)、.addClass(classNames)、.addClass(funcntion)

    className 代表字符串,例如:.addClass('class1 class2……')

    classNames 代表数组,例如:.addClass(['class1', 'class2'])

    将指定的类添加到匹配元素集合中的每个元素,每次都是追加 class。

    底层调用的是 setAttribute( "class", finalValue ) 方法添加 class。

  • .hasClass(className)

    是否给任意匹配到的元素分配了该类。

    底层是通过 getAttribute( "class" ).indexOf() 来判断是否存在。

    javascript
    // jQuery 内部大致是这样实现的:
    function hasClass(className) {
      var classAttr = this.getAttribute("class");  // 获取 class 属性值
      return classAttr && classAttr.indexOf(className) !== -1;  // 检查是否包含该类名
    }
  • .removeClass()、.removeClass(className)、.removeClass(classNames)、.removeClass(function)

    给匹配元素集中的每个元素删除单个类、多个类或所有类。

    底层调用的是 removeAttribute( "class", finalValue ) 方法。

  • .toggleClass()、.toggleClass(className[, state])、.toggleClass(classNames[, state])

    根据类的存在或状态参数的值,在匹配到元素的集合中,给每个元素添加或删除一个或多个类。

3. 属性操作

① .attr(attributeName) :获取匹配元素集合中第一个元素的属性值。

    .attr(attributeName, value)、.attr(attributes) :为每个匹配元素设置一个或多个属性。

attributes 代表对象,例如:.attr({id:'container', name:'yxts'}})

底层调用了原生的 getAttribute() API。

可以获取或设置自定义的属性值与标准的属性值。

② .removeAttr(attributeName) :在匹配到元素的集中,给每个元素删除一个属性。

底层调用了原生的 removeAttribute() API。

可以删除自定义的属性值与标准的属性值。

只能删除单个属性。

③ .prop(propertyName) :获取匹配到元素集合中第一个元素的属性值。

    .prop(propertyName, value)、.prop(propertys) :为每个匹配元素设置一个或多个属性。

propertys 代表对象,例如:.prop({id:'container', name:'yxts'}})

不能获取到自定义的属性值,但可以设置自定义的属性值。

设置自定义的属性其实是放到缓存里去了(此元素的 js 实例中)。

④ .removeProp(propertyName) :删除匹配元素集的属性。

只能删除用户自定义添加的 prop,不能删除元素本身的属性。

注:attr 和 prop 区别?

① 如果操作的是元素的固有属性,则建议使用 prop。

② 如果操作的是元素自定义的属性,则建议使用 attr。

自定义 data-xxx 属性的操作

  • .data()、.data(key) :获取匹配元素集中第一个元素的自定义属性的值。

  • .data(key, value)、.data(obj) :为每个匹配元素设置一个或多个自定义属性。

  • .removeData([name]) :会删除 data() 函数给匹配元素属性添加的数据和 data() 函数绑定的自定义属性。

    注意:data 函数添加的属性会被移除,但是如果属性同时在标签上定义了就不会被移除。所有操作都是操作内存里的对象缓存。

原理

html
<body>
  <ul id="xq-1" data-name="yxts" data-age="18">
    <li>1</li>
    <li>2</li>
  </ul>
</body>

<script>
  console.log($("ul").data())
  setTimeout(() => {
    $("ul").data("name", "xq")
    console.log("%O", document.getElementById("xq-1"))
  }, 100)
</script>

4. 节点操作

1)增加 / 移动

① append() :父元素将子元素追加到末尾。参数可以是文本、html 字符串、jQuery 对象、元素对象、选择器(如果是选择器选中了 DOM 元素,那么会把选中的移动到此处)。

    对象1.append(对象2) :将对象2添加到对象1元素内部,并且在末尾。

② prepend() :父元素将子元素追加到开头

    对象1.prepend(对象2) :将对象2添加到对象1元素内部,并且在开头。

③ appendTo() :参数可以是 jQuery 对象、元素对象。

    对象1.appendTo(对象2) :将对象1添加到对象2内部,并且在末尾。

html
<ul>
  <li class="li-1">li-1</li>
  <li class="li-2">li-2</li>
  <li class="li-3">li-3</li>
  <li class="li-4">li-4</li>
  <li class="li-5">li-5</li>
</ul>
<li class="li-7">我是li-7</li>

<script>
  // 1.给ul的尾部插入内容
  $('<li>')
    .addClass('li-6')
	.css('color', 'red')
	.text('我是li-6')  // 创建一个li元素(必须是一个jQuery对象)

	// 方式一: 支持 jQuery对象
	// .appendTo( $('ul') )
	// 方式二: 支持 字符串类型的选择器
	// .appendTo( 'ul' )
	// 方式三: 支持 元素对象
	.appendTo( document.querySelector('ul') )


  $('.li-7').appendTo('ul')  // append
</script>

④ prependTo()

    对象1.prependTo(对象2) :将对象1添加到对象2内部,并且在开头。

⑤ after() :添加元素到元素后边。

    对象1.after(对象2) :将对象2添加到对象1后边。对象1和对象2是兄弟关系。

⑥ before() :添加元素到元素前边。

    对象1.before(对象2) :将对象2添加到对象1前边。对象1和对象2是兄弟关系。

⑦ insertAfter()

    对象1.insertAfter(对象2) :将对象1添加到对象2后边。对象1和对象2是兄弟关系。

⑧ insertBefore()

    对象1.insertBefore(对象2) :将对象1添加到对象2前边。对象1和对象2是兄弟关系。

2)删除

① .remove()、.remove( 'selector1, selector2 ...' ) :删除匹配的元素集,自身也会删除。

    selector 参数:仅支持字符串类型选择器。用来筛选匹配元素集的元素来删除。

② empty() :删除匹配元素集的所有子节点,自身不会删除。

    对象.empty() :将对象的后代元素全部清空,但是保留当前对象以及其属性节点。

3)替换

① .replaceAll(target) :用匹配到的元素集替换每个目标元素。

    replaceAll 参数: 1.字符串类型的选择器 2.jQuery对象 3.元素对象。

② .replaceWidth(newContent)、.replaceWidth(function) :用新内容替换匹配元素集中的每个元素,并返回被移除的元素集。

    newConten 参数的类型:字符串文本/html字符串, DOM element, array of DOM elements, or jQuery object。

4)复制

① .clone()、.clone(withDataAndEvents) :对匹配的元素集执行深度复制,底层是调用了 elem.cloneNode(true) 来复制元素。

    withDataAndEvents 参数 :布尔值,是否复制该元素的事件处理程序和数据,默认值为 false。

第三章:事件处理

一、事件基础

1. 绑定方法

事件监听方式一:直接调用 jQuery 对象中的事件处理函数来监听。例如:click、mouseenter ……。

事件监听方式二:调用 jQuery 对象中的 on 函数来监听,使用 off 函数来取消监听。

javascript
/*
  .on(events, selector, data, handler)
*/

// 1. 只传处理函数
$('#btn').click(function() { console.log('点击'); });
// 等价于:.on('click', null, undefined, function)

// 2. 传数据和处理函数
$('#btn').click({userId: 123}, function(e) {
  console.log('用户ID:', e.data.userId); // 123
});
// 等价于:.on('click', null, {userId: 123}, function)

// 3. .on() 的常见用法
$('#container').on('click', function(e) {
  console.log('我被单击了!');
});

// 4. 直接使用 .on() 的完整形式
$('#container').on('click', '.btn', {userId: 123}, function(e) {
  console.log('命名空间 + 事件委托 + 数据传递');
});

// 5. .on() 的其他用法
// 事件委托(通过父元素监听)
$('#container').on('click', '#btn', function() {
  console.log('按钮被点击');
});
// 添加带命名空间的事件
$('#btn').on('click.myModule', function() {
  console.log('模块的点击事件');
});
$('#btn').off('click.myModule')

这两种方式有什么区别? 以 click 事件为例

  • click 是 on 的简写。它们重复监听,不会出现覆盖情况,都支持事件委托,底层用的是 addEventListener。

    javascript
    // jQuery 源码
    jQuery.each(
      "blur focus focusin focusout resize scroll click dblclick " +
      "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
      "change select submit keydown keypress keyup contextmenu".split(" "),
      function(_i, name) {
        // 动态生成事件方法
        jQuery.fn[name] = function(data, fn) {
          return arguments.length > 0
                 ? this.on(name, null, data, fn) // 绑定事件
                 : this.trigger(name);           // 触发事件
        };
      }
    );
  • on 函数支持给事件添加命名空间。on 函数还可以接受一个 selector 参数,用于筛选可触发事件的后代元素。如果 on 没有使用 selector 的话,那么和使用 click 是一样的。

2. 其他

1)this 指向

click 函数和 on 绑定单击事件的 this 指向:都是指向原生的 DOM Element。

javascript
// jQuery 底层实现原理
var lisEl = $('ul li').get() // [li, li, li]
for(var liEl of lisEl ){
  liEl.addEventListener('click', function() {
    console.log(this)
    // 一般都转为 jQuery 对象
    console.log($(this))
  })
}
2)事件冒泡

jQuery 为了更好的兼容 IE 浏览器,底层并没有实现事件捕获。仅有事件冒泡。

3)jQuery 的事件对象

jQuery 事件系统的规范是根据 W3C 的标准来制定 jQuery 事件对象。

  • 原始事件对象的大多数属性都被复制到新的 jQuery 事件对象上。如以下原生的事件属性被复制到 jQuery 事件对象中:

    altKey, clientX, clientY, currentTarget, data, detail, key, keyCode, offsetX, offsetY, originalTarget, pageX, pageY, relatedTarget, screenX, screenY, target, ……

  • jQuery 事件对象通用的属性(以下属性已实现跨浏览器的兼容):

    ptarget、relatedTarget、pageX、pageY、which、metaKey

  • jQuery 事件对象常用的方法:

    ppreventDefault() :取消事件的默认行为(例如,a 标签、表单事件等)。

    pstopPropagation() :阻止事件的进一步传递(例如,事件冒泡)。

要访问其它事件的属性,可以使用 event.originalEvent 获取原生对象。

javascript
// 1. 使用 on 监听
$('span').on('click', function($event) {
  console.log('span', this);
  console.log($event); // jQuery 事件对象
  console.log($event.originalEvent); // span 的事件对象
});
5)jQuery 的事件委托

可以通过 event.target 获取到当前监听事件的元素;event.currentTarget 获取到的是处理事件的元素。

例子:一个 ul 中存放多个 li,使用事件委托的模式来监听 li 中子元素的点击事件。

html
<ul id="list" class="panel">
  <li class="li-1">li-1
    <p class="p1">我是p元素</p>
  </li>
  <li class="li-2">li-2
    <p  class="p2">我是p元素</p>
  </li>
</ul>

<script>
  // 1. 直接调用jQuery对象中的click事件函数
  // $('ul').click(function(event) {
  //   console.log(event.target) // DOM Element : ul li p
  // })

  // 2. 使用jQuery对象中的on函数来监听
  $('ul').on('click', 'li p', function(event) {
    console.log(event.target) // DOM Element : p
  })
</script>

二、常用事件函数

鼠标事件 (Mouse Events)

  • .click()

  • .dblclick()

  • .hover()

    javascript
    // hover 底层使用的是: mouseenter or mouseleaver
    $('ul').hover(function() {
      console.log('鼠标悬浮在ul')
    }, function() {
      console.log('鼠标离开在ul')
    })
  • .mousedown():鼠标按下。

  • .mouseup():鼠标释放。

  • .mouseenter()

  • .mouseleave()

  • .mouseover()

  • .mouseout()

  • .mousemove():鼠标移动。

  • .contextmenu()

  • .toggle():点击切换(jQuery 1.9+ 已移除)。

    javascript
    // 旧版本用法(现已废弃)
    $('#btn').toggle(
      function() { console.log('第一次点击'); },
      function() { console.log('第二次点击'); }
    );
    
    // 现代替代方案
    $('#btn').click(function() {
      $(this).toggleClass('active');
    });

键盘事件 (Keyboard Events)

  • .keydown()
  • .keypress()
  • .keyup()

文档事件 (Document Loading Events)

  • .ready():当 DOM 结构解析完成时触发(不等待图片等外部资源)。

  • load():当整个页面完全加载完成时触发(包括图片、样式表、脚本等所有资源)。

    javascript
    $(window).load(function() {
      // 所有图片、CSS、JS 都加载完毕
      console.log('页面完全加载完成');
    });
    
    // 也可以监听特定元素的加载
    $('img').load(function() {
      console.log('图片加载完成');
    });
  • unload():当用户离开页面时触发(刷新、关闭、跳转到其他页面)。

表单事件 (Form Events)

  • .blur()
  • .focus()
  • .change():该事件在表单元素的内容改变时触发 ( <input>, <keygen>, <select>, 和 <textarea>)
  • .submit()
  • .select():当用户选中文本内容时触发的事件,主要用于文本输入框(<input type="text">)和文本域(<textarea>)。

浏览器事件 (Browser Events)

  • .resize()
  • .scroll()

第四章:高级

一、插件机制

插件是增强 jQuery 功能的。

编写 jQuery 插件的步骤

  1. 新建一个插件对应的 JS 文件(命名规范:jquery.插件名.js)。
  2. 在立即执行函数中编写插件,这样可以避免插件中的变量与全局变量冲突。
  3. 在 jQuery 的原型对象上新增一些方法。
  4. 最后在 html 中导入就可以像使用其他 jQuery 对象方法一样使用了。

增强通过 Jquery 对象的功能

$.fn.extend(object)Jquery.fn.extend(object)

$.fn.xxx = function(){} 或者 Jquery.fn.xxx = function(){}

xxx 是 jQuery 实例要增强的方法名。

javascript
;(function(window, $){
  $.fn.extend({
    // 定义了一个check()方法
    // 所有的jq对象都可以调用该方法
    check: function () {
      // 让复选框选中
      // this: 调用该方法的jq对象
      this.prop("checked", true);
    },
    // 定义了一个uncheck()方法
    uncheck: function () {
      // 让复选框不选中
      this.prop("checked", false);
    }
  });
})(window, jQuery)

增强 JQeury 对象自身的功能

$.extend(object) Jquery.extend(object)

javascript
/*
  对全局方法扩展2个方法
    扩展min方法:求2个值的最小值
    扩展max方法:求2个值最大值
*/
$.extend({
  max:function (a,b) {
    // 返回两数中的较大值
      return a >= b ? a:b;
  },
  min:function (a,b) {
    // 返回两数中的较小值
    return a <= b ? a:b;
  }
});

// 调用全局方法
var max = $.max(4,3);
alert(max);

var min = $.min(1,2);
alert(min);

二、动画

1. animate()

执行一组 CSS 属性的自定义动画,支持属性值为数字的 CSS 属性上创建动画。

语法:.animate( properties [, duration ] [, easing ] [, complete ] ) 、.animate(properties ,options)

  • properties:要执行动画的 CSS 属性

    具体值

    百分比

    特殊值

    • "show" - 显示元素
    • "hide" - 隐藏元素
    • "toggle" - 切换显示/隐藏状态

    相对值

    • "+=" - 增加
    • "-=" - 减少
  • duration:动画持续时间

    "fast" - 相当于200毫秒

    "slow":600毫秒

    "normal":400毫秒(默认值)

  • easing:缓动函数

    "swing" - 缓入缓出(默认值)

    "linear" - 线性变化

  • complete:动画完成时的回调函数

  • options:{ duration: XXX, easing: XXX, complete: function(){} }

2. 显示和隐藏方式

显示:show()、show([speed,[easing],[fn]])

隐藏:hide()、hide([speed,[easing],[fn]])

切换:toggle()、toggle([speed],[easing],[fn])、toggle(options)

  • speed:动画的速度。三个预定义的值("slow", "normal", "fast")或表示动画时长的毫秒数值(如:1000)。

  • easing:用来指定切换效果,默认是 "swing"。

    • swing:动画执行时效果是 先慢,中间快,最后又慢。
    • linear:动画执行时速度是匀速的。
  • fn:在动画完成时执行的函数,每个元素执行一次。

  • options:{ duration: XXX, easing: XXX, complete: function(){} }

3. 滑动显示和隐藏方式

slideDown([speed],[easing],[fn])

slideUp([speed,[easing],[fn]])

slideToggle([speed],[easing],[fn])

4. 淡入淡出显示和隐藏方式

fadeIn([speed],[easing],[fn])

fadeOut([speed],[easing],[fn])

fadeToggle([speed,[easing],[fn]])

5. 动画队列

jQuery 匹配元素中的 animate 和 delay 动画是通过一个动画队列 (queue) 来维护的。例如执行下面的动画都会添加到动画队列中:

  • .hide() 、 .show():底层调用的是 .animate()。
  • .fadeIn() 、.fadeOut():底层调用的是 .animate()。
  • .animate()、delay()
  • ......

queue():查看当前选中元素中的动画队列。

.stop( [clearQueue ] [, jumpToEnd ] ):停止匹配元素上当前正在运行的动画。

  • clearQueue :一个布尔值,指示是否也删除排队中的动画。默认为 false
  • jumpToEnd :一个布尔值,指示是否立即完成当前动画。默认为 false
动画队列代码
html
<head>
  <style>
    .box{
      position: relative;
      width: 100px;
      height: 100px;
      background-color: pink;
    }
  </style>
</head>
<body>
  <button class="start">开始动画</button>  
  <button class="stop">停止动画</button>  
  <button class="queue">查看动画队列</button> 

  <div class="box">box</div>

  <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
  <script>
    $(function() {
      var $box = $('.box')
      $('.start').click(function() {
        $box.animate({
          top: 100
        }, 5000)

        $box.animate({
          left: 100
        }, 5000)

        $box.animate({
          top: 0
        }, 5000)

        $box.animate({
          left: 0
        }, 5000)
      })

      $('.queue').click(function() {
        console.log( $box.queue() )  // 查看动画队列 fx
      })

      $('.stop').click(function() {
        // 停止 fx 动画队列 (停止当前执行的动画, 还会继续执行动画队列中其它的动画)
        $box.stop() // 等价于 stop(false, false)

        // 停止所有的动画, 清空了动画队列
        // $box.stop(true)

        // 清空了动画队列, 立即执行完当前的动画
        // $box.stop(true, true)
      })
    })
  </script>
</body>

三、遍历

jquery 对象的 each

jquery对象.each(function(index,element){});

  • index:就是元素在集合中的索引。
  • element:就是集合中的每一个元素对象(JS 对象)。
  • this:集合中的每一个元素对象(JS 对象)。

回调函数返回值:

  • false:如果当前 function 返回为 false,则结束循环 (break) 。
  • true:如果当前 function 返回为 true,则结束本次循环,继续下次循环 (continue) 。
javascript
// jquery对象的 each 源码
each: function(obj, callback) {
  var length, i = 0;

  if (isArrayLike(obj)) {
    length = obj.length;
    for (i = 0; i < length; i++) {
      // 这里用call调用了this指向的DOM element
      if (callback.call(obj[i], i, obj[i]) === false) {
        break;
      }
      if (callback.call(obj[i], i, obj[i]) === true) {
        continue;
      }
    }
  } else {
    for (i in obj) {
      // 这里用call调用了this指向的DOM element
      if (callback.call(obj[i], i, obj[i]) === false) {
        break;
      }
      if (callback.call(obj[i], i, obj[i]) === true) {
        continue;
      }
    }
  }

  return obj;
}

举个例子

javascript
// 只处理偶数索引的元素
$('li').each(function(index, element) {

  // 如果是奇数索引,返回 true 跳过
  if (index % 2 !== 0) {
    console.log('跳过索引:', index);
    return true;  // 相当于 continue,跳到下一次循环
  }

  // 下面的代码只有偶数索引才会执行
  console.log('处理索引:', index);
  $(element).css('color', 'red');
});

全局 each 方式

$.each(object, [callback])

注:可以遍历数组和对象,JS 对象也可以遍历。

for..of

jquery 3.0 版本之后提供的方式。

原理是 jQuery 对象实现了迭代器协议。

javascript
for(元素对象 of 容器对象){
}

注:元素对象为 JS 对象。

四、ajax

jQuery 中有 AJAX 模块,该模块是在 XMLHttpRequest 的基础上进行了封装,语法如下:

  • $.ajax( [settings ] ) - 默认用 GET 请求从服务器加载数据, 会返回 jQXHR 对象,可以利用该对象的 abort 方法来取消请求。
  • $.ajax( url [, settings ] )
  • $.get( url [, data ] [, success ] [, dataType ] ) - 发起 GET 请求,底层调用的还是 $.ajax()
  • $.post( url [, data ] [, success ] [, dataType ] ) - 发起 POST 请求,底层调用的还是 $.ajax()

可以使用免费测试 http 服务的网站 https://httpbin.org 来学习使用 jQuery 中的 AJAX 模块。

请求参数(Parameters)

  • url:指定发送请求的 URL。

  • method / type:用于指定请求的类型(e.g. "POST", "GET", "PUT"),默认为 GET。

  • data:指定要发送到服务器的数据(PlainObject or String or Array)。

  • processData:当 data 是一个对象时,jQuery 从对象的键/值对生成数据字符串。除非该 processData 选项设置为 false。例如,{a: "bc", d: "e,f"} 被转换为字符串 "a=bc&d=e%2Cf",默认为 true。

  • header:请求头的内容(PlainObject)。

  • contentType:默认值:application/x-www-form-urlencoded; charset=UTF-8。向服务器发送请求时指定内容类型。

    • application/x-www-form-urlencoded; charset=UTF-8:请求体的数据以键值对字符串形式提交,如:a=bc&d=e%2Cf。
    • application/json; charset=UTF-8:指定为 JSON 字符串类型。
    • 为 false,代表是 multipart/form-data。表单类型,一般用于上传文件。
  • dataType:预期的服务器响应类型(json, xml, text...)。默认会根据响应的类型来自行推断类型。

  • timeout:请求超时的时间,它以毫秒为单位。

  • beforeSend:这是一个在发送请求之前调用的函数,返回 false 会取消网络请求。

  • success:请求成功回调的函数。

  • error:请求失败回调的函数。

data 选项可以包含两种形式:查询字符串形式 key1=value1&key2=value2 或者对象形式 {key1: 'value1', key2: 'value2'}。如果使用后一种形式,数据会在发送之前使用 jQuery.param() 转换为查询字符串。通过设置 processDatafalse 可以跳过这个处理过程。

如果 post 请求体是 formdata 对象,那么需要设置 contentType 为 false、processData 为 false。

1. 发起 get

javascript
// 1. url上添加查询字符串
$.ajax({
  url: 'http://httpbin.org/get?cityId=404100&keyWord=天河公园',
  method: "GET",
  success: function(res) {
    console.log(res)
  }
})

// 2. 支持在data中提交参数
$.ajax({
  url: 'http://httpbin.org/get',
  method: "GET",
  data: {
    cityId: '504100',
    keyWord: '小蛮腰'
  },
  success: function(res) {
    console.log(res)
  }
})

// 3. 给get请求添加请求头
$.ajax({
  url: 'http://httpbin.org/get',
  method: "GET",
  data: {
    cityId: '504100',
    keyWord: '小蛮腰'
  },
  headers: {
    accessToken: 'aaaaabbbbbcccccc'  // 比如你登录成功之后, 后台会返回一个token
  },
  success: function(res) {
    console.log(res)
  }
})

// 4. get简写 
$.get('http://httpbin.org/get')
  .then(function(res) {  // jQuery 1.8; done
    console.log(res)
  })
  .catch(function() {  //  fail
    console.log('catch')
  })
  .always(function() {  // finally  
    console.log('always')
  })

2. 发起 post

javascript
// 1. 在url中提交查询字符串(比较少见)
$.ajax({
  url: 'http://httpbin.org/post?cityId=404100&keyWord=天河公园',
  method: "POST",
  success: function(res) {
    console.log(res)
  }
})

// 2. 在data中提交查询字符串
$.ajax({
  url: 'http://httpbin.org/post',
  method: "POST",
  data: {
    cityId: '504100',
    keyWord: '杭州'
  },
  contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
  // dataType: 'json', // 自动推断, response 的 content-type
  success: function(res) {
    console.log(res)
  }
})

// 3. 在data中JSON字符串
$.ajax({
  url: 'http://httpbin.org/post',
  method: "POST",
  data: JSON.stringify({
    cityId: '504100',
    keyWord: '杭州'
  }),
  contentType: 'application/json; charset=UTF-8',
  success: function(res) {
    console.log(res)
  }
})

// 4. 在data中FormData
var formData = new FormData()
// <form> <input name="cityId" value="404100"/> <input name="keyWord" value="小蛮腰"/> </form>
formData.append('cityId', 404100)
formData.append('keyWord', '杭州')
$.ajax({
  url: 'http://httpbin.org/post',
  method: "POST",
  data: formData,
  processData: false, // processData:true, 会将data对象转成查询字符串
  contentType: false, // 使用原生XHR, 默认的contentType就是formData
  success: function(res) {
    console.log(res)
  }
})

// 5. 在添加请求头
var formData = new FormData()
formData.append('cityId', 404100)
formData.append('keyWord', '杭州')
$.ajax({
  url: 'http://httpbin.org/post',
  method: "POST",
  data: formData,
  processData: false, // processData:true, 会将data对象转成查询字符串
  contentType: false, // 使用原生XHR, 默认的contentType就是formData
  headers: {
    token: 'xxxxxxssssssssmmmmm'
  },
  success: function(res) {
    console.log(res)
  }
})

// 6. POST简写
$.post('http://httpbin.org/post', {
  cityId: '504100',
  keyWord: '杭州'
})
.then(function(res) {
  console.log(res)
})
preview
图片加载中
预览

Released under the MIT License.