大家好,我是 零一 。虽然现在很多前端项目都在用Vue、React,但依赖jquery的项目也不少,尤其是年代比较久远的项目,那些还正在维护jquery项目的你,是否想将jquery从你的项目中移除?毕竟这个库那么大,你能用到的代码也就只有15%~30%,而且jquery对各个浏览器的兼容性也做了很大的处理(代码量up up),但其实很多老项目也不会去考虑兼容很边缘的浏览器了,所以其实jquery中兼容处理的代码也没太大必要
最近新发现了一个有意思的工具,仅上线2周,就有 600+
的Star,它说能帮助你的项目脱离对jquery的依赖,感觉是个不错的想法,一起来看看吧~
使用方式
这个工具的名字叫 replace-jquery ,据说是能帮你从项目中自动查找所有用到的jquery方法,并生成一套原生js的方法去替代
先来搞一个极简的jquery项目
index.html

main.js

测试一下页面的功能,是OK的
接下来我们用 replace-jquery 工具试着移除一下 main.js
中的jquery代码
先全局下载一下
npm install -g replace-jquery
- 1.
然后在项目目录使用,语法为 replace-jquery 目标js文件 生成的js文件
replace-jquery main.js newMain.js
- 1.
该工具会自动找到你文件中所有用到的jquery方法。此处有一个确认的步骤,你可以选择想要替换哪些方法(默认是全选的)

按回车键即可完成替换,并生成新的文件
export class Utils {
constructor(selector) {
this.elements = Utils.getSelector(selector);
this.element = this.get(0);
return this;
}
on(events, listener) {
events.split(' ').forEach((eventName) => {
this.each((el) => {
const tNEventName = Utils.setEventName(el, eventName);
if (!Array.isArray(Utils.eventListeners[tNEventName])) {
Utils.eventListeners[tNEventName] = [];
}
Utils.eventListeners[tNEventName].push(listener);
// https://github.com/microsoft/TypeScript/issues/28357
if (el) {
el.addEventListener(eventName.split('.')[0], listener);
}
});
});
return this;
}
remove() {
this.each((el) => {
el.parentNode.removeChild(el);
});
return this;
}
css(css, value) {
if (value !== undefined) {
this.each((el) => {
Utils.setCss(el, css, value);
});
return this;
}
if (typeof css === 'object') {
for (const property in css) {
if (Object.prototype.hasOwnProperty.call(css, property)) {
this.each((el) => {
Utils.setCss(el, property, css[property]);
});
}
}
return this;
}
const cssProp = Utils.camelCase(css);
const property = Utils.styleSupport(cssProp);
return getComputedStyle(this.element)[property];
}
static getSelector(selector, context) {
if (selector && typeof selector !== 'string') {
if (selector.length !== undefined) {
return selector;
}
return [selector];
}
context = context || document;
// For performance reasons, use getElementById
// eslint-disable-next-line no-control-regex
const idRegex = /^#(?:[\w-]|\\.|[^\x00-\xa0])*$/;
if (idRegex.test(selector)) {
const el = document.getElementById(selector.substring(1));
return el ? [el] : [];
}
return [].slice.call(context.querySelectorAll(selector) || []);
}
get(index) {
if (index !== undefined) {
return this.elements[index];
}
return this.elements;
}
each(func) {
if (!this.elements.length) {
return this;
}
this.elements.forEach((el, index) => {
func.call(el, el, index);
});
return this;
}
static setEventName(el, eventName) {
// Need to verify https://stackoverflow.com/questions/1915341/whats-wrong-with-adding-properties-to-dom-element-objects
const elementUUId = el.eventEmitterUUID;
const uuid = elementUUId || Utils.generateUUID();
// eslint-disable-next-line no-param-reassign
el.eventEmitterUUID = uuid;
return Utils.getEventName(eventName, uuid);
}
static setCss(el, prop, value) {
// prettier-ignore
let cssProperty = Utils.camelCase(prop);
cssProperty = Utils.styleSupport(cssProperty);
el.style[cssProperty] = value;
}
static camelCase(text) {
return text.replace(/-([a-z])/gi, (s, group1) => group1.toUpperCase());
}
static styleSupport(prop) {
let vendorProp;
let supportedProp;
const capProp = prop.charAt(0).toUpperCase() + prop.slice(1);
const prefixes = ['Moz', 'Webkit', 'O', 'ms'];
let div = document.createElement('div');
if (prop in div.style) {
supportedProp = prop;
} else {
for (let i = 0; i < prefixes.length; i++) {
vendorProp = prefixes[i] + capProp;
if (vendorProp in div.style) {
supportedProp = vendorProp;
break;
}
}
}
div = null;
return supportedProp;
}
static generateUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
// eslint-disable-next-line no-bitwise
const r = (Math.random() * 16) | 0;
// eslint-disable-next-line no-bitwise
const v = c === 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
static getEventName(eventName, uuid) {
return `${eventName}__EVENT_EMITTER__${uuid}`;
}
}
Utils.eventListeners = {};
export default function $utils(selector) {
return new Utils(selector);
}
- 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.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
简单看了一下,似乎就是把我们用到的jquery方法替换成了简单的原生方法,并封装在 Utils
这个类中,那么我们每次调用 $("xxx")
时,其实就是在调用该类上的方法,那么对这个文件做一些修改
// 此处删除export
class Utils {
// ...省略一些代码
}
Utils.eventListeners = {};
// 此处删除 export default,并将函数 $utils改成 $
function $(selector) {
return new Utils(selector);
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
这样就相当于我们在全局模拟jquery定义了一个 $
方法。此时html文件中的jquery引用就可以删除了,并把我们刚才生成的文件引进来

再去页面中尝试操作dom,可以看到效果跟之前一样,成功!
补充
如果你想用该工具生成jquery所有api的替代文件,即生成一个 super-mini-jquery
,你可以这么做
replace-jquery --build-all super-mini-jquery.js
- 1.
将代码混淆丑化以后大概只有10kb

因为这个工具刚发布才2个星期不到,只实现了大部分的jquery代码替换,比如 ajax
暂时是没办法替换的,你如果尝试去替换,工具也会提醒你
无法替换ajax
总的来说,这个工具想法不错,希望后期能支持更多的语法替换!