终于有人对 jQuery下手了,一键移除项目对它的依赖

开发 前端
最近新发现了一个有意思的工具,仅上线2周,就有 600+ 的Star,它说能帮助你的项目脱离对jquery的依赖,感觉是个不错的想法,一起来看看吧~

 [[424009]]

大家好,我是 零一 。虽然现在很多前端项目都在用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代码

先全局下载一下

  1. npm install -g replace-jquery 

然后在项目目录使用,语法为 replace-jquery 目标js文件 生成的js文件

  1. replace-jquery main.js newMain.js 

该工具会自动找到你文件中所有用到的jquery方法。此处有一个确认的步骤,你可以选择想要替换哪些方法(默认是全选的)

 

 

生成过程

 

按回车键即可完成替换,并生成新的文件

  1. export class Utils { 
  2.     constructor(selector) { 
  3.         this.elements = Utils.getSelector(selector); 
  4.         this.element = this.get(0); 
  5.         return this
  6.     } 
  7.  
  8.     on(events, listener) { 
  9.         events.split(' ').forEach((eventName) => { 
  10.             this.each((el) => { 
  11.                 const tNEventName = Utils.setEventName(el, eventName); 
  12.                 if (!Array.isArray(Utils.eventListeners[tNEventName])) { 
  13.                     Utils.eventListeners[tNEventName] = []; 
  14.                 } 
  15.                 Utils.eventListeners[tNEventName].push(listener); 
  16.  
  17.                 // https://github.com/microsoft/TypeScript/issues/28357 
  18.                 if (el) { 
  19.                     el.addEventListener(eventName.split('.')[0], listener); 
  20.                 } 
  21.             }); 
  22.         }); 
  23.  
  24.         return this
  25.     } 
  26.     remove() { 
  27.         this.each((el) => { 
  28.             el.parentNode.removeChild(el); 
  29.         }); 
  30.         return this
  31.     } 
  32.     css(css, value) { 
  33.         if (value !== undefined) { 
  34.             this.each((el) => { 
  35.                 Utils.setCss(el, css, value); 
  36.             }); 
  37.             return this
  38.         } 
  39.         if (typeof css === 'object') { 
  40.             for (const property in css) { 
  41.                 if (Object.prototype.hasOwnProperty.call(css, property)) { 
  42.                     this.each((el) => { 
  43.                         Utils.setCss(el, property, css[property]); 
  44.                     }); 
  45.                 } 
  46.             } 
  47.             return this
  48.         } 
  49.         const cssProp = Utils.camelCase(css); 
  50.         const property = Utils.styleSupport(cssProp); 
  51.         return getComputedStyle(this.element)[property]; 
  52.     } 
  53.     static getSelector(selector, context) { 
  54.         if (selector && typeof selector !== 'string') { 
  55.             if (selector.length !== undefined) { 
  56.                 return selector; 
  57.             } 
  58.             return [selector]; 
  59.         } 
  60.         context = context || document; 
  61.  
  62.         // For performance reasons, use getElementById 
  63.         // eslint-disable-next-line no-control-regex 
  64.         const idRegex = /^#(?:[\w-]|\\.|[^\x00-\xa0])*$/; 
  65.         if (idRegex.test(selector)) { 
  66.             const el = document.getElementById(selector.substring(1)); 
  67.             return el ? [el] : []; 
  68.         } 
  69.         return [].slice.call(context.querySelectorAll(selector) || []); 
  70.     } 
  71.     get(index) { 
  72.         if (index !== undefined) { 
  73.             return this.elements[index]; 
  74.         } 
  75.         return this.elements; 
  76.     } 
  77.     each(func) { 
  78.         if (!this.elements.length) { 
  79.             return this
  80.         } 
  81.         this.elements.forEach((el, index) => { 
  82.             func.call(el, el, index); 
  83.         }); 
  84.         return this
  85.     } 
  86.     static setEventName(el, eventName) { 
  87.         // Need to verify https://stackoverflow.com/questions/1915341/whats-wrong-with-adding-properties-to-dom-element-objects 
  88.         const elementUUId = el.eventEmitterUUID; 
  89.         const uuid = elementUUId || Utils.generateUUID(); 
  90.         // eslint-disable-next-line no-param-reassign 
  91.         el.eventEmitterUUID = uuid; 
  92.         return Utils.getEventName(eventName, uuid); 
  93.     } 
  94.     static setCss(el, prop, value) { 
  95.         // prettier-ignore 
  96.         let cssProperty = Utils.camelCase(prop); 
  97.         cssProperty = Utils.styleSupport(cssProperty); 
  98.         el.style[cssProperty] = value; 
  99.     } 
  100.     static camelCase(text) { 
  101.         return text.replace(/-([a-z])/gi, (s, group1) => group1.toUpperCase()); 
  102.     } 
  103.     static styleSupport(prop) { 
  104.         let vendorProp; 
  105.         let supportedProp; 
  106.         const capProp = prop.charAt(0).toUpperCase() + prop.slice(1); 
  107.         const prefixes = ['Moz''Webkit''O''ms']; 
  108.         let div = document.createElement('div'); 
  109.  
  110.         if (prop in div.style) { 
  111.             supportedProp = prop; 
  112.         } else { 
  113.             for (let i = 0; i < prefixes.length; i++) { 
  114.                 vendorProp = prefixes[i] + capProp; 
  115.                 if (vendorProp in div.style) { 
  116.                     supportedProp = vendorProp; 
  117.                     break
  118.                 } 
  119.             } 
  120.         } 
  121.  
  122.         div = null
  123.         return supportedProp; 
  124.     } 
  125.     static generateUUID() { 
  126.         return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { 
  127.             // eslint-disable-next-line no-bitwise 
  128.             const r = (Math.random() * 16) | 0
  129.             // eslint-disable-next-line no-bitwise 
  130.             const v = c === 'x' ? r : (r & 0x3) | 0x8
  131.             return v.toString(16); 
  132.         }); 
  133.     } 
  134.     static getEventName(eventName, uuid) { 
  135.         return `${eventName}__EVENT_EMITTER__${uuid}`; 
  136.     } 
  137.  
  138. Utils.eventListeners = {}; 
  139.  
  140. export default function $utils(selector) { 
  141.     return new Utils(selector); 

简单看了一下,似乎就是把我们用到的jquery方法替换成了简单的原生方法,并封装在 Utils 这个类中,那么我们每次调用 $("xxx") 时,其实就是在调用该类上的方法,那么对这个文件做一些修改

  1. // 此处删除export 
  2. class Utils { 
  3.  // ...省略一些代码 
  4.  
  5. Utils.eventListeners = {}; 
  6.  
  7. // 此处删除 export default,并将函数 $utils改成 $ 
  8. function $(selector) { 
  9.     return new Utils(selector); 

这样就相当于我们在全局模拟jquery定义了一个 $ 方法。此时html文件中的jquery引用就可以删除了,并把我们刚才生成的文件引进来

 

 

删除jquery,注入替代品

 

 

再去页面中尝试操作dom,可以看到效果跟之前一样,成功!

补充

如果你想用该工具生成jquery所有api的替代文件,即生成一个 super-mini-jquery ,你可以这么做

  1. replace-jquery --build-all super-mini-jquery.js 

将代码混淆丑化以后大概只有10kb

 

 

super-mini-jquery包体大小

 

 

 因为这个工具刚发布才2个星期不到,只实现了大部分的jquery代码替换,比如 ajax 暂时是没办法替换的,你如果尝试去替换,工具也会提醒你

无法替换ajax

总的来说,这个工具想法不错,希望后期能支持更多的语法替换!

 

责任编辑:张燕妮 来源: 前端印象
相关推荐

2020-02-23 16:33:02

GitHub印度子公司

2018-12-26 09:03:30

物联网IOT智能

2024-07-17 13:11:22

2020-09-16 13:08:17

微信儿童版天眼查腾讯

2023-08-23 19:01:09

PythonExcel语言

2015-09-22 09:41:56

技术程序员

2015-09-29 11:37:45

技术依赖程序员

2021-06-13 12:03:46

SaaS软件即服务

2021-10-09 00:02:04

DevOps敏捷开发

2022-03-27 20:32:28

Knative容器事件模型

2015-01-23 10:04:56

bug程序员

2023-11-24 12:36:00

模型训练

2023-10-05 18:49:12

.Net​Newtonsof源码

2023-11-02 08:43:08

protocgo兼容

2020-03-31 15:03:56

Spring Boot代码Java

2022-01-10 11:01:04

FedoraifcfgLinux

2021-06-29 11:21:41

数据安全网络安全黑客

2021-02-14 00:21:37

区块链数字货币金融

2020-07-29 09:21:34

Docker集群部署隔离环境

2020-11-30 08:34:44

大数据数据分析技术
点赞
收藏

51CTO技术栈公众号