文章目录
一、基本原理
jQuery 库中有一段关于初始化的源码,其是整个 jQuery 的根基,本人简化后,将其分为如下四个部分:
(function () {
// 第一部分
var jQuery = function (selector, context) {
return new jQuery.fn.init(selector, context)
}
window.jQuery = window.$ = jQuery
// 第二部分
jQuery.fn = jQuery.prototype = {
constructor: jQuery,
length: 0,
toArray: function () {},
get: function (num) {},
pushStack: function (elems) {},
each: function (callback) {},
map: function (callback) {},
slice: function () {},
first: function () {},
last: function () {},
even: function () {},
odd: function () {},
eq: function (i) {},
end: function () {},
push: push,
sort: arr.sort,
splice: arr.splice,
}
// 第三部分
jQuery.fn.init = function (selector, context, root) {}
jQuery.fn.init.prototype = jQuery.fn
// 第四部分 - 继续为 jQuery.fn 对象添加函数, 此处省略
})()
核心源码分析
第一部分
jQuery 库是一个自执行函数,其内部定义了一个名为 jQuery
的函数(一般称这个函数为 jQuery 核心函数
), 并将函数
赋值给 window.jQuery
和 window.$
, 分析到这里,我们能知道,只要我们在项目中引用了 jQuery 库, 那么我们就可以通过全局变量 window.jQuery
或 window.$
来访问 jQuery 核心函数, 该函数的返回值为 jQuery.fn.init
对象
第二部分
定义 jQuery.fn
对象,并在对象中定义了很多 jQuery 的基础函数,其实通过对象名 fn
就能看出,这个对象是专门
用来提供函数调用的(一般称这个对象为 jQuery 核心对象
),该对象是一个伪数组,数组每个记录中还会包含选取的 DOM 元素
第三部分
定义 jQuery.fn.init
对象,其对象内部我们先不研究,重要看 jQuery.fn.init.prototype = jQuery.fn
这句代码,其在
jQuery.fn.init
对象的原型链上添加了 jQuery.fn
对象,也就是代表 jQuery.fn.init
对象可以访问 jQuery.fn
对象中定
义的全部函数,所以我们调用 jQuery 核心函数后, 虽然返回的是 jQuery.fn.init
对象,却能访问 jQuery.fn
对象中的函数
第四部分
后面主要是继续对 jQuery.fn
对象进行扩展,向 jQuery 核心对象中添加更多的函数
小结:
前面分析完 jQuery 库的核心流程后,我们要能区分出, jQuery 核心函数、jQuery 核心对象的区别,剩下的
就是对照着 jQuery 文档进行学习 jQuery 核心函数 和 jQuery 核心对象的各种用法
二、jQuery 核心函数
1. 传入回调函数
官方语法:jQuery( callback ) 或 $( callback )
DOM 解析完成事件,不需要等待图片下载完成,当 DOM 解析完成后,会执行传入的 callback
,该用法可以防止
DOM 解析完成前,提前使用 DOM 元素导致的无法选取的问题,如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>jQuery</title>
</head>
<body>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script>
console.log(document.querySelector('div')) // 结果为 null
</script>
<div></div>
</body>
</html>
代码是自上而下运行,上面例子中,运行到 <script>
脚本获取 div
元素时, div
还没有被 DOM 解析,所以导致获取
不到,而通过向 jQuery 核心函数中传入回调函数的方式,就可以避免这个问题,如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>jQuery</title>
</head>
<body>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script>
$(() => {
console.log(document.querySelector('div')) // 成功获取元素
})
</script>
<div></div>
</body>
</html>
其实我最推荐的方式是改变一下代码顺序,把 <script>
写在最后,让 DOM 先解析,然后再执行 <script>
来避免这个问题,如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>jQuery</title>
</head>
<body>
<div></div>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script>
console.log(document.querySelector('div'))
</script>
</body>
</html>
2. 传入选择器字符串
官方语法:jQuery( selector [, context ] )
参数 | 必须 | 作用 |
---|---|---|
selector | 是 | 根据传入的选择器查找元素 |
context | 否 | 在指定的目标元素范围内,根据传入的选择器查找元素 |
只传入 selector,根据传入的选择器查找元素:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>jQuery</title>
</head>
<body>
<div id="container"></div>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script>
console.log($('#container')) // 结果:jQuery 核心对象伪数组,该对象内部包含选取的 DOM 元素
</script>
</body>
</html>
传入 selector 和 context,在指定的目标元素范围内,查找元素:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>jQuery</title>
<style>
div {
width: 100px;
height: 100px;
border: 1px solid black;
}
</style>
</head>
<body>
<div id="container1">
<div name="inner"></div>
</div>
<div id="container2">
<div name="inner"></div>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script>
let container2 = $('#container2')
$('div[name=inner]', container2).text('container2 中的元素被选中')
</script>
</body>
</html>
3. 传入标签字符串
常用语法:jQuery( htmlString )
向 jQuery 核心函数内传入 html 标签字符串,可以生成新的 DOM 元素,通常与 appendTo
等连用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>jQuery</title>
</head>
<body>
<div id="container"></div>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script>
// 向 #container 中添加一个按钮
$('<input type="button" value="click">').appendTo($('#container'))
</script>
</body>
</html>
三、jQuery 核心对象的基础函数
1. get 函数:从 jQuery 核心对象中获取真正的 DOM 元素
官方语法:jQuery 核心对象.get( index )
前面已经知道了 jQuery 核心对象是一个伪数组,如果想获取每个 jQuery 核心对象中保存的 DOM 元素,就可以使
用 get
函数来完成
从 jQuery 核心对象中获取真正的 DOM 元素:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>jQuery</title>
</head>
<body>
<div></div>
<p></p>
<p></p>
<p></p>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script>
console.log($('div').get(0)) // 结果:真正的 DOM 元素 <div></div>
console.log($('p').get(2)) // 结果:真正的 DOM 元素,最后一个 <p></p>
</script>
</body>
</html>
2. each 函数:遍历 jQuery 核心对象
官方语法:jQuery 核心对象.each( function( index ) )
想遍历 jQuery 核心对象伪数组时,就可以使用 each
函数, 该函数需要一个回调函数作为参数,每一次遍历都会
执行该回调函数,并会传入一个当前遍历的索引下标,在回调函数内部可以通过 this
获取处于当前下标的真正
的 DOM 元素,注意:如果要在回调函数内部使用 this
,就不要用箭头函数的方式, 要用 function
的方式声明回调函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>jQuery</title>
</head>
<body>
<p>第一个元素</p>
<p>第二个元素</p>
<p>第三个元素</p>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script>
$('p').each(function (index) {
console.log('第 ' + index + ' 元素的内容为: ' + this.innerText)
})
</script>
</body>
</html>
3. index 函数:获取元素在 jQuery 核心对象伪数组中的下标
官方语法:jQuery 核心对象…index( selector || element )
通过指定 选择器 或 DOM 元素对象,查询目标在 jQuery 核心对象伪数组中的下标
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>jQuery</title>
</head>
<body>
<p id="first"></p>
<p id="second"></p>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script>
// 通过选择器获取元素在 jQuery 核心对象伪数组中的下标
console.log($('p').index('#first')) // 结果: 0
// 通过 DOM 元素对象,获取元素在 jQuery 核心对象伪数组中的下标
console.log($('p').index($('#second').get(0))) // 结果: 1
</script>
</body>
</html>
四、插件机制
常用语法:
扩展 jQuery 核心函数中的方法:jQuery.extend( object1 )
扩展 jQuery 核心对象中的方法:jQuery.fn.extend( object1 )
当我们感觉 jQuery 中的方法不够用,想自定义添加时,可以使用插件机制来扩展 jQuery 方法,扩展的方式有两
种,第一种是扩展 jQuery 核心函数中的方法, 另一种是扩展 jQuery 核心对象中的方法
扩展 jQuery 核心函数中的方法后,直接使用 window.$
或 window.jQUery
就可以访问,如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>jQuery</title>
</head>
<body>
<p id="first"></p>
<script>
window.$ = '字符串'
</script>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script>
$.extend({
myMethod() {
console.log('自定义函数')
},
})
$.myMethod() // 执行加入到 jQuery 工具的自定义方法
</script>
</body>
</html>
扩展 jQuery 核心对象中的方法,需要先获取到 jQuery 核心对象,然后才能访问,如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>jQuery</title>
</head>
<body>
<p id="first"></p>
<script>
window.$ = '字符串'
</script>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script>
$.fn.extend({
myMethod() {
console.log('自定义函数')
},
})
$('p').myMethod() // 执行加入到 jQuery 核心对象的自定义函数
</script>
</body>
</html>
五、多库共存
官方语法:jQuery.noConflict()
当 jQuery 默认导出的变量名 window.$
或 window.jQuery
与其他 JS 中定义的变量名冲突时,可以使用该方法,让
jQuery 将变量名的使用权交出,然后为 jQuery 重新定义新的变量名
自己定义的 window.$
被 jQuery 导出的 jQuery 核心函数覆盖:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>jQuery</title>
</head>
<body>
<script>
window.$ = '字符串'
</script>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script>
console.log($) // 结果: jQuery 核心函数
</script>
</body>
</html>
让 jQuery 将变量名的使用权交出,然后为 jQuery 重新定义新的变量名:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>jQuery</title>
</head>
<body>
<script>
window.$ = '字符串'
</script>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script>
var jQuery$ = jQuery.noConflict()
console.log($) // 结果:自定义变量
console.log(jQuery$) // 结果: jQuery 核心函数
</script>
</body>
</html>