jQuery是js的一个插件,可以从官网下载,直接引入就可以使用,其设计宗旨是”Write Less,Do More”,其本质上是一个类似语法糖的东西,集成了js中很多常用的方法和选择器,使得代码写起来更简单

下载完之后我们就可以直接引入它,包含.min是压缩后的,内存更小,未压缩的可以作为源码阅读查错

1
<script src="jquery-3.6.0.js"></script>

当然如果不想下载也可以使用谷歌或者微软的CDN

jQuery常用功能

下面记录几种常用功能的jQuery使用方法

DOM对象的获取

相比于使用js原本获取DOM对象的语句,jQuery简单了很多,只用一个$符号表示DOM对象选取

1
var block = $(".block")

我们知道如果获取一个DOM,则一般在js中使用document.querySeletor(".block"),但是如果要获取同属于这个类的所有dom就要使用document.querySelectorAll(".block")

而jQuery中则会直接返回一个对象数组,返回所有满足条件的对象,比如如果有两个class为block的dom,则可以用block[0]block[1]来分别使用这两个dom

CSS样式设置

在jQuery中设置css样式,只要简单调用css方法即可,比如我要将所有block的背景颜色变为红色,只需要写如下代码

1
block.css("background-color","red")

css函数支持多条属性的添加,需要用一个花括号包裹,然后在里面写css属性,格式如下,注意这里原本带有小横杠的属性名字用驼峰命名法代替

1
block.css({color:"#fff", fontSize:"30px"})

jQuery还有一个方便的特性是链式操作,即对对象修改之后会作为返回值返回,比如刚才我们两次对css的修改可以简单地并在一起处理

1
2
block.css("background-color","red")
.css({color:"#fff", fontSize:"30px"})

类名的增删

这个本质上也就是对js原生的方式的简写,代码示例如下,这样就能给所有block添加类,并将第一个block的类去掉

1
2
$(".block").addClass("spcBlock")
$(".block:nth-of-type(1)").removeClass("spcBlock")

属性的修改与查询

属性的修改则是使用封装的attr函数

1
$(".block:nth-of-type(1)").attr("data-id", 1)

当然如果我们不填attr函数的第二个参数,那就相当于是直接查询对应的属性

1
console.log($(".block:nth-of-type(1)").attr("data-id"))

HTML内容的修改

在JS里面我们经常对标签包裹的HTML内容进行修改,jQuery对这个方法也进行了封装

1
$(".block:nth-of-type(1)").html("方块修改")

同样,这个函数也可以用来查询html,括号内不填参数即可

事件添加

两种方式如下

1
2
3
4
5
6
$('.block').click(function(event){
console.log(event)
})
$('.block').on('click',function(){
console.log('click')
})

简易jQuery的实现

所以,jQuery就是一个封装好的使用更方便的一个框架,或者说插件

现在我们来尝试自己封装一个简易的jQuery,实现以上的功能

创建一个jquery-simple.js,然后引入,开始实现上述功能,之前的测试代码如下所示,我们的目标就是使得这些代码能够成功运行,那么功能就算实现了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div class="block">方块1</div>
<div class="block">方块2</div>
<script>
var block = $(".block")
block.css("background-color", "red")
.css({ color: "#fff", fontSize: "30px" })
$(".block").addClass("spcBlock")
$(".block:nth-of-type(1)").removeClass("spcBlock")
$(".block:nth-of-type(1)").attr("data-id", 1)
console.log($(".block:nth-of-type(1)").attr("data-id"))
$(".block:nth-of-type(1)").html("方块修改")
$(".block").click(function (event) {
console.log(event)
})
$(".block").on("click", function () {
console.log("click")
})
</script>

DOM的获取

首先我们需要实现可以用$符号来进行dom的查询并返回

1
2
3
4
5
6
var $ = function(selector){
var elements = document.querySelectorAll(selector)
// 解构
elements = [...elements]
return elements
}

这里我们对elements进行数组解构,因为querySelectorAll的返回值是一个nodelist,不好使用forEach,不太方便我们接下来的封装操作

接下来就是对elements方法的添加,我们将方法添加到elements的原型对象上,因为css方法的参数稍微复杂一点,我们最后来封装,先将其它简单的功能封装一下

类名的增删

1
2
3
4
5
6
7
8
elements.__proto__.addClass = function (classname) {
this.forEach(item => item.classList.add(classname))
return this;
}
elements.__proto__.removeClass = function (classname) {
this.forEach(item => item.classList.remove(classname))
return this;
}

属性和HTML的修改和查找

属性和HTML的修改和查找的实现非常相似,同样都可以通过判断arguments的长度来确定对应的功能,然后相应地实现即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 属性
elements.__proto__.attr = function (attr, value) {
// 对每个dom添加属性
if (arguments.length == 2) {
this.forEach(item => item.setAttribute(attr, value))
return this;
}
// 返回第一个dom的属性值
if (arguments.length == 1) {
return elements[0].getAttribute(attr)
}
}
// HTML内容
elements.__proto__.html = function (htmlValue) {
if (arguments.length == 1) {
this.forEach(item => item.innerHTML = htmlValue)
return this;
}
if (arguments.length == 0) {
return elements[0].innerHTML
}
}

事件的添加

事件添加和属性添加其实本质上是相同的,只是将属性替换成了回调函数

1
2
3
4
5
6
elements.__proto__.click = function(callback){
this.forEach(item => item.addEventListener('click',callback))
}
elements.__proto__.on = function(eventName,callback){
this.forEach(item => item.addEventListener(eventName,callback))
}

css添加

最后处理一下稍微复杂一些的css添加函数

css添加有两种,一种是只有两个字符串作为参数,另一种是将css对象作为参数,我们根据这两种情况分别处理即可,具体方式见如下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
elements.__proto__.css = function(){
if(arguments.length == 2){
elements.forEach(item => item.style[arguments[0]] = arguments[1])
return this;
}
if(arguments.length == 1 && typeof arguments[0]=='object'){
elements.forEach(item => {
var params = arguments[0];
for(let key in params){
item.style[key] = params[key]
}
})
return this;
}
}

代码总览

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
var $ = function (selector) {
var elements = document.querySelectorAll(selector)
elements = [...elements]
// 类名
elements.__proto__.addClass = function (classname) {
this.forEach(item => item.classList.add(classname))
return this;
}
elements.__proto__.removeClass = function (classname) {
this.forEach(item => item.classList.remove(classname))
return this;
}
// 属性
elements.__proto__.attr = function (attr, value) {
if (arguments.length == 2) {
this.forEach(item => item.setAttribute(attr, value))
return this;
}
if (arguments.length == 1) {
return elements[0].getAttribute(attr)
}
}
// HTML内容
elements.__proto__.html = function (htmlValue) {
if (arguments.length == 1) {
this.forEach(item => item.innerHTML = htmlValue)
return this;
}
if (arguments.length == 0) {
return elements[0].innerHTML
}
}
// 事件添加
elements.__proto__.click = function(callback){
this.forEach(item => item.addEventListener('click',callback))
}
elements.__proto__.on = function(eventName,callback){
this.forEach(item => item.addEventListener(eventName,callback))
}
// css修改
elements.__proto__.css = function(){
if(arguments.length==2){
elements.forEach(item => item.style[arguments[0]]=arguments[1])
return this;
}
if(arguments.length==1 && typeof arguments[0]=='object'){
elements.forEach(item => {
var params = arguments[0];
for(let key in params){
item.style[key] = params[key]
}
})
return this;
}
}
return elements
}

这样,50来行代码我们就完成了一个简易的jQuery,封装的时候特别要注意的一点就是方法的返回值,也就是上述代码中频繁出现的return this,在元素修改后需要将其返回出去,这样才能实现jQuery链式操作特性

就写到这吧,晚安