最近新发现了一个有意思的工具,仅上线2周,就有600+的Star,它说能帮助你的项目脱离对jquery的依赖,感觉是个不错的想法,一起来看看吧~
这个工具的名字叫replace-jquery[1],据说是能帮你从项目中自动查找所有用到的jquery方法,并生成一套原生js的方法去替代
先来搞一个极简的jquery项目
index.html
index.html
main.js
main.js
测试一下页面的功能,是OK的
演示动图
接下来我们用 replace-jquery 工具试着移除一下 main.js 中的jquery代码
先全局下载一下
npm install -g replace-jquery
然后在项目目录使用,语法为replace-jquery 目标js文件 生成的js文件
replace-jquery main.js newMain.js
该工具会自动找到你文件中所有用到的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);}
简单看了一下,似乎就是把我们用到的jquery方法替换成了简单的原生方法,并封装在Utils这个类中,那么我们每次调用$("xxx")时,其实就是在调用该类上的方法,那么对这个文件做一些修改
// 此处删除exportclass Utils { // ...省略一些代码}Utils.eventListeners = {};// 此处删除 export default,并将函数 $utils改成 $function $(selector) { return new Utils(selector);}
这样就相当于我们在全局模拟jquery定义了一个$方法。此时html文件中的jquery引用就可以删除了,并把我们刚才生成的文件引进来
删除jquery,注入替代品
再去页面中尝试操作dom,可以看到效果跟之前一样,成功!
如果你想用该工具生成jquery所有api的替代文件,即生成一个super-mini-jquery,你可以这么做
replace-jquery --build-all super-mini-jquery.js
将代码混淆丑化以后大概只有10kb
super-mini-jquery包体大小
因为这个工具刚发布才2个星期不到,只实现了大部分的jquery代码替换,比如ajax暂时是没办法替换的,你如果尝试去替换,工具也会提醒你
无法替换ajax
总的来说,这个工具想法不错,希望后期能支持更多的语法替换!
对于这个工具,你们有什么看法,欢迎在评论区留言讨论~
我是零一,分享技术,不止前端。关注我,了解更多前端新姿势~
[1]
replace-jquery: https://github.com/sachinchoolur/replace-jquery