为什么放弃jQuery

前言

首先,直接操作dom的编程方式已经成为过去,数据驱动才是正途!
其次,不一定非要舍弃jQuery,只是可以,选择权在自己手上!
下面只是就事论事

落幕

2018年7月 全球最大的同性交友社区(Github)被微软收购后的 52 天,改版并放弃了 jQuery 。这一举动让我等搬运工陷入了沉思。

Why?

随着ECMAScript标准的更新,原生js已经可代替jQuery,给我babel一个面子,不要再说兼容不支持的话!
下面举两个比较常用的方面来说明:

  • jQuery Api可以使用原生轻松实现
  • 使用 fetch 来代替 ajax;
    Fetch API 是基于 Promise 设计,更符合目前的异步解决方案。什么是目前的异步解决方案?翻看上一篇async & await

具体实现对比(部分)

选择器

1
2
3
4
5
//jq
$("#a .b");

//Native
document.querySelectorAll("#a .b");

插入

1
2
3
4
5
6
7
8
9
10
11
12
 //jq
$(selector).append(html);
//prepend
//before
//after

//Native
document.querySelectorAll(selector).insertAdjacentHTML("beforeend", html);
//beforebegin 开始标签之前 before
//afterbegin 开始标签之后 prepend
//beforeend 结束标签之前 append
//afterbegin 结束标签之后 after

类操作

1
2
3
4
5
6
7
8
9
10
11
 //jq
$(selector).addClass(className);
//hasClass
//removeClass
//toggleClass

//Native
document.querySelectorAll(selector).classList.add(className, className, className...);
//contains(className) 检测是否存在
//removeClass(className, className, className...) 删除
//toggle(className, true|false) 切换

ajax

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
58
59
60
61
62
//jq
$.ajax({
//.................
});

//Native
(async () => {
try{
const res = await req(url, {headers: {Accept: "text/html"}});
if(......){
.......
}
} catch {

}
}());

function req(url, data) { //自己封装,仅供参考
let sendurl = url;
let setting = {
method: data.type ? data.type : "get",
headers: new Headers({
"Accept": "application/json, text/javascript, */*; q=0.01",
"Pragma": "no-cache",
"Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
"X-Requested-With": "XMLHttpRequest"
}),
credentials: "include"
};

if(data.headers){
const headers = setting.headers;
for(let attr in data.headers){
if(headers.has(attr)){
headers.set(attr, data.headers[attr]);
} else {
headers.append(attr, data.headers[attr]);
}
}
}

if (setting.method == "post") {
setting.body = data.param ? paramData(data.param) : "";
} else {
sendurl = sendurl + (data.param ? "?" + paramData(data.param) : "");
}

return fetch(sendurl, setting).then((response) => {
if (response.status >= 200 && response.status < 300) {
return response;
} else {
throw new Error(response.statusText);
}
}).then((response) => {
const accept = setting.headers.get("accept");
if(accept.includes("/json")){
return response.json();
} else if(accept.includes("/html")){
return response.text();
}
});
}

原生实现类jQuery的库

上手才是关键,下面实现了部分jQuery的Api(代码构建编译部分省略),可能功能有所差异,但是就是这个味儿~

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<!DOCTYPE html>
<html lang="en">
<title>test</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<head>
</head>
<body>
<div class="test" actid="111"></div>
</body>
<script>
class xy {
constructor(selector){
this.dom = document.querySelectorAll(selector);
this.length = document.querySelectorAll(selector).length;
}

eq(index){
this.dom = [this.dom[index]];
return this;
}

attr(name){
return this.dom[0].getAttribute(name);
}

children(index){
let childrenList = [];
for(let i = 0;i < this.dom.length;i++){
childrenList.push(this.dom[i].children);
}

let arr = [];
for(let i = 0;i < childrenList.length;i++){
arr.push(index != undefined ? childrenList[i][index] : childrenList[i]);
}

return arr.length > 1 ? arr : arr[0];
}

append(htmlStr){
// for(let i = 0;i < this.dom.length;i++){
// this.dom[i].insertAdjacentHTML("beforeend", htmlStr);
// }
this.circulationFun("dom.insertAdjacentHTML('beforeend', '" + htmlStr + "')");
}

html(htmlStr){
this.circulationFun("dom.innerHTML = '" + htmlStr.replace(/\s*/g,"") + "'");
}

remove(){
this.circulationFun("dom.parentNode.removeChild(dom)");
}

addClass(className){
this.classFun("add", className);
}

removeClass(className){
this.classFun("remove", className);
}

toggleClass(className){
this.circulationFun("dom.classList.toggle('" + className + "')");
}

classFun(order, className){
const classArr = className.split(" ");
let code = "dom.classList." + order + "(";
for(let i = 0;i < classArr.length;i++){
code += "'" + classArr[i] + "',";
}
code = code.substr(0, code.length - 1);
code += ")";
this.circulationFun(code);
}

circulationFun(code){
for(let i = 0;i < this.dom.length;i++){
new Function("dom", "i", code)(this.dom[i], i);
}
}

//你可以不停的去扩展
}

function $xy(selector){
return new xy(selector);
}

$xy(".test").attr("actid");
//output 111
</script>
Do the best!