jQuery 入门使用

前言

鲁迅说过:不会 jQuery 的前端工程师不是好工程师。

公司的很多项目都还在用 jQuery 来作为主力的框架,配合 RequireJS 来做模块分割

正文

ready

在 jQuery 中,有很多种方式来 DOMContentLoaded 或者 load 事件监听的效果

一般我们会把代码包裹在 load 或者 DOMContentLoaded 的回调中:

1
2
3
document.addEventListener('load', function () {
// 核心代码
})

包裹在其中的原因是因为这个回调会在文档加载完成后调用,这意味着我们可以放心的使用 dom 操作,而不会发生 dom 元素不存在的情况

在 jQuery 中,我们可以使用如下写法:

1
2
3
4
5
6
7
8
9
10
11
jQuery(function () {
// dom 准备完成
})

jQuery(document).ready(function () {
// dom 准备完成
})

jQuery.ready.then(function () {
// dom 准备完成
})

获取 dom 元素

在原生的 JavaScript 中,我们会使用 document.getElementsByClassnamedocument.getElementByIddocument.getElementsByTagName 来获取相应的 dom 元素

当然,我们也可以使用 document.querySelector 或者 document.querySelectorAll 来获取 dom 元素,这个相比上面三个的有点就是不用区分是标签,还是类名,还是 id ,但需要完整写出待查询的内容的类别。比如类名是由一个点开始,而 id 则是由一个哈希符号开始。

1
2
3
4
5
6
7
8
9
document.addEventListener('load', function () {
document.getElementById('id1') // 查找 #id1 的元素
document.getElementsByTagName('p') // 查找 p 标签元素
document.getElementsByClassName('class1') // 查找 class1 类的元素

document.querySelector('#id1')
document.querySelector('p')
document.querySelector('.class1')
})

在 jQuery 中,我们只需要直接将查询的内容传入 jQuery 函数即可

1
2
3
4
5
jQuery(function () {
jQuery('#id1')
jQuery('.class1')
jQuery('p')
})

通过 jQuery 函数返回之后,我们就得到了一个 jQuery 的对象, jQuery 封装了很多常用的方法供我们使用,大大减少了原生写法带来的代码量。

监听事件

在原生的 JavaScript 中,我们可以听过直接往 dom 元素上挂在 onXXX ,或者使用 dom.addEventListener 来绑定事件回调

1
2
3
4
5
// onXXX 方式
document.onload = function () {}

// addEventListener 方式
document.addEventListener('load', function () {})

在 jQuery 中,提供了一个 on 方法来绑定事件回调

1
2
3
4
jQuery(function () {
// 给 p 标签绑定点击事件
jQuery('p').on('click', function () {})
})

如果我们想模拟出发某些事件,我们可以使用 trigger 方法

1
2
3
4
jQuery(function () {
// 触发 click 事件
jQuery('p').trigger('click')
})

在 3.3 版本之前,我们可以使用直接使用 click 方法来绑定和触发,不过在 3.3 版本开始就废弃了这个 api 了

1
2
3
4
5
// 绑定
jQuery('p').click(function () {})

// 触发
jQuery('p').click()

直接通过方法名来进行注册这种方式在 3.3 版本就被废弃了,比如 resize 或者 scroll 都已被废弃

而 on 方式在 1.7 版本就有了,所以推荐一律使用 on 方法来注册事件回调。

除了直接监听,我们也可以使用广为人知的一种方式,那就是事件代理

事件代理的好处就是我们只需要对某个根节点进行监听,通过判断真正触发事件的元素来进行对应的操作

这不仅可以减少内存占用,而且可以动态监听新增的节点

假设我们现在有如下 dom

1
2
3
4
5
<ul class="list">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>

在原生的 JavaScript 中,我们可以通过下面的代码实现事件代理

1
2
3
4
5
6
7
const ulEl = document.querySelector('ul.list')
ulEl.addEventListener('click', (e) => {
const target = e.target
if (target.tagName.toLowerCase() === 'li') {
console.log('click')
}
})

在 jQuery 中,我们使用 delegate 或者是 on 来事件

其中 delegate 在 3.0 版本被废弃,而 on 是在 1.7 版本之后支持事件代理的写法

1
2
3
4
5
6
7
8
9
// delegate 方式
jQuery('ul.list').delegate('li', 'click', function () {
console.log('click')
})

// on 方式
jQuery('ul.list').on('click', 'li', function () {
console.log('click')
})

这里建议统一使用 on ,方便理解。

文档增删

在原生 JavaScript 中,增删文档最常用的就是 innerHTML , innerText , append , prepend , after , before 这几个接口了

append , prepend 是相对自身的子元素位置进行插入,而 after , before 则是相对自身位置进行插入

假设现在有如下 dom

1
2
3
4
<div class="parent">
<div class="child1"></div>
<div class="child2"></div>
</div>

此时如果我们想在 .child1 前增加一个 .child0 的 div ,那么可以进行如下操作

创建一个对应的 div

1
2
3
const c0 = document.createElement('div')
c0.classList.add('child0')
c0.textContent = 'child0'

使用 prepend

1
2
const parent = document.querySelector('.parent')
parent.prepend(c0)

或者使用 before

1
2
const c1 = document.querySelector('.child1')
c1.before(c0)

在 JQuery 中,也提供了相似的 API ,即 html , text , append , appendTo , prepend , prependTo , before , after , insertBefore , insertAfter

这里面有几个以 To 结尾的方法,其实和它们对应的没有 To 后缀的方法是一样的功能,只不过“反转”了控制

假设现在有如下 dom

1
2
3
<div class="container">
<div class="item1"></div>
</div>

.item1 后面增加一个 .item2 的话,我们可以用 appendappendTo 两种方式来实现

1
2
3
4
5
// append
jQuery('.container').append("<div class='item2'></div>")

// appendTo
jQuery("<div class='item2'></div>").appendTo('.container')

ajax

原生的 JavaScript 提供了 XMLHttpRequest 对象来让我们发送请求,它的写法如下:

get 请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const xhr = new XMLHttpRequest()
xhr.addEventListener('readystatechange', () => {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
// 请求成功
console.log('结果:', JSON.parse(xhr.responseText))
} else {
// 请求失败
}
}
})
// 使用 apifox 的测试接口
const url = new URL('https://echo.apifox.com/get')
url.searchParams.set('id', '109')
url.searchParams.set('name', 'lwf')
xhr.open('get', url.toString(), true)
xhr.send()

post 请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const xhr = new XMLHttpRequest()
xhr.addEventListener('readystatechange', () => {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
// 请求成功
console.log('结果:', JSON.parse(xhr.responseText))
} else {
// 请求失败
}
}
})
// 使用 apifox 的测试接口
const url = new URL('https://echo.apifox.com/post')
xhr.open('post', url.toString(), true)
xhr.setRequestHeader('content-type', 'application/json')
const json = {
id: 109,
name: 'lwf',
}
xhr.send(JSON.stringify(json))

在 jQuery 中,帮我们封装了 XHRHttpRequest 对象,通过 jQuery.ajax 来使用

get 请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
jQuery.ajax({
method: 'get',
data: {
id: 109,
name: 'lwf',
},
url: 'https://echo.apifox.com/get',
success: function (data) {
console.log('data: ', data)
},
error: function (e) {
console.error(e)
},
})

post 请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
jQuery.ajax({
method: 'post',
data: JSON.stringify({
id: 109,
name: 'lwf',
}),
headers: {
'content-type': 'application/json',
},
url: 'https://echo.apifox.com/post',
success: function (data) {
console.log('data: ', data)
},
error: function (e) {
console.error(e)
},
})

除了 jQuery.ajax , jQuery 也导出了一些简写的 API ,即 jQuery.getjQuery.post

后记

我还是很不喜欢写原生 js 的,一方面旧项目的代码残破不堪,各种补丁,另一方面,以我的水平很难分离代码逻辑和 dom 操作,写起来实在是有点心力交瘁。

不过这都是工作嘛,工作讲究的就是一个完成任务,能跑就行。

不要跟我说什么 Vue 、 React 、 Angular 。老夫写项目就是 jQuery 一把梭,梭哈就完事。