专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

如何优雅地编写一个高逼格的JS插件?

  在一个风和日丽的早晨,我正悠闲地喝着Coffe,突然领导向我走来,我赶紧熟练地切出VSCode,淡定自若地问:领导,什么事?领导拍了拍我的肩膀:你上次封装的方法同事跟我反馈使用起来很不错啊,你不如做成JS插件给大家用吧。我放下了手中的马克杯,甩了一下眼前仅剩的几根刘海:没问题啊,小Case!随即开始摸鱼。。。。原型链写法
  要开始编写插件就得先了解JS模块化,早期的模块化是利用了函数自执行来实现的,在单独的函数作用域中执行代码可以避免插件中定义的变量污染到全局变量,举个栗子,以下代码实现了一个简单随机数生成的插件:;(function(global){usestrict;varMyPluginfunction(name){this。namename};MyPlugin。prototype{say:function(){console。log(欢迎你:,this。name)},random:function(min0,max1){if(minNumber。MAXSAFEINTEGERmaxNumber。MAXSAFEINTEGER){returnMath。floor(Math。random()(maxmin1))min}}};函数自执行将this(全局下为window)传入,并在其下面挂载方法global。MyPluginMyPlugin;兼容CommonJs规范导出if(typeofmodule!undefinedmodule。exports)module。exportsMyPlugin;})(this);
  直接使用script标签引入该插件,接着new一个实例就能使用插件啦:varaFnnewMyPlugin()varnumaFn。random(10,20)console。log(num)打印一个1020之间的随机数闭包式写法
  上面的插件使用时如果调用say方法,会打印方法中的欢迎字样,并显示初始化的name值:varaFnnewMyPlugin(呀哈哈)aFn。say()欢迎你:呀哈哈
  但由于属性能被直接访问,插件中的变量就可以随意修改,这可能是我们不想看到的:varaFnnewMyPlugin(呀哈哈)aFn。namenullaFn。say()欢迎你:null
  那么如果要创建私有变量,可以利用JS闭包原理来编写插件,我们使用工厂模式来创建函数,再举个栗子,如下代码实现了一个简单正则校验的插件:;(function(global){usestrict;varMyPluginfunction(value){varvalvaluevarreg{phone:1〔3456789〕d{9},number:?d。?d};return{getRegs(){returnreg},setRegs(params){reg{。。。reg,。。。params}},isPhone(){reg。phone。test(val)console。log(这是手机号)returnthis},isNumber(){reg。number。test(val)console。log(这是数字)returnthis}};};函数自执行将this(全局下为window)传入,并在其下面挂载方法global。MyPluginMyPlugin;兼容CommonJs规范导出if(typeofmodule!undefinedmodule。exports)module。exportsMyPlugin;})(this);
  这时我们再调用插件,其内部的变量是不可访问的,只能通过插件内部的方法查看修改:varaFnnewMyPlugin()console。log(aFn。reg)undefinedvarregaFn。getRegs()console。log(reg){phone:{。。。。},number:{。。。。。}}
  上面代码中我们在isPhoneisNumber方法的最后都返回了this,这是为了实现如下的链式调用:varaFnnewMyPlugin(13800138000)aFn。isPhone()。isNumber()log:这是手机号这是数字仿JQuery写法
  这种写法是仿造JQ实现的一种编写模式,可以省去调用时new实例化的步骤,并实现类似(xxx)。someFn(。。。。)这样的调用方法,在需要频繁DOM操作的时候就很适合这么编写插件。笔者以前会在小项目中自己实现一些类JQ选择器操作的功能插件,来避免引入整个JQ,实现插件的核心思路如下:varFnFunction(params){returnnewFn。prototype。init(params)}Fn。prototype{init:function(){}}Fn。prototype。init。prototypeFn。prototype
  可以看出核心是对JS原型链的极致利用,首先主动对其原型上的init方法进行实例化并返回,init相当于构造函数的效果,而此时返回的实例里并没有包含Fn的方法,我们调用时JS自然就会从init的原型对象上去查找,于是最终init下的原型才又指向了Fn的原型,通过这种套娃的手法,使得我们能够不通过实例化Fn又能正确地访问到Fn下的原型对象。
  说了这么多,还是举个栗子,以下代码实现了一个简单的样式操作插件:;(function(global){usestrict;varMyPluginfunction(el){returnnewMyPlugin。prototype。init(el)};MyPlugin。prototype{init:function(el){this。eltypeofelstring?document。querySelector(el):el;},setBg:function(bg){this。el。style。backgroundbg;returnthis},setWidth:function(w){this。el。style。widthw;returnthis},setHeight:function(h){this。el。style。heighth;returnthis}};MyPlugin。prototype。init。prototypeMyPlugin。prototypescript标签引入插件后全局下挂载一个的方法global。MyPlugin;})(thiswindow);
  使用演示:!页面元素helloworld
  为元素设置背景:(app)。setBg(ff0)
  为元素设置背景并改变宽高:(app)。setBg(ff0)。setHeight(100px)。setWidth(200px)
  工程化插件
  假设以后会有多人同时开发的情况,仅靠一个JS维护大型插件肯定是独木难支,这时候就需要组件化把颗粒度打细,将插件拆分成多个文件,分别负责各自的功能,最终再打包成一个文件引用。如今ES模块化已经可以轻松应对功能拆分了,所以我们只需要一个打包器,Rollup。js就是不错的选择,有了它我们可以更优雅地编写插件,它会帮我们打包。许多大型框架例如Vue、React都是用它打包的。
  Rollup是一个用于JavaScript的模块打包器,它将小段代码编译成更大更复杂的东西,例如库或应用程序。Rollup官网〔1〕创建一个示例
  下面我们一步步实现这个工程化的插件,没有那么复杂,先创建一个目录:mkdirpmyprojectsrc
  接着运行npminit进行项目初始化,一路回车,接着为项目安装Rollup:npminstallsavedevrollup
  根目录下创建入口文件index。js,以及src下的main。js用于等下测试:index。jsimportmainfrom。srcmain。js;console。log(main);srcmain。jsexportdefaulthelloworld!;
  根目录下创建rollup。config。jsimportbabelfromrolluppluginbabelbabel:将最终代码编译成es5,我们的开发代码可以不用处理兼容性。importcommonjsfromrollupplugincommonjsimportresolvefromrolluppluginnoderesolveresolve、commonjs:用于兼容可以依赖commonjs规范的包。exportdefault{input:index。js,output:〔{file:distmain。umd。js,format:umd,name:bundlename,},{file:distmain。es。js,format:es,},{file:distmain。cjs。js,format:cjs,},〕,plugins:〔babel({exclude:nodemodules,}),resolve({jsnext:true,main:true,browser:true,}),commonjs(),〕,}
  把上面的依赖安装一下,运行:npminstallsavedevbabelcorebabelpresetenvrolluppluginbabellatestrolluppluginnoderesolverollupplugincommonjs
  修改package。json,增加一条脚本命令:。。。。。。。scripts:{。。。。。。dev:rollupcw},
  最后运行npmrundev看看效果吧:
  示例结果
  打包最终文件位置:
  运行nodedistmain。cjs。js:
  打包文件格式说明1。umd
  集合了CommonJS、AMD、CMD、IIFE为一体的打包模式,看看上面的helloworld会被打包成什么:(function(global,factory){typeofexportsobjecttypeofmodule!undefined?module。exportsfactory():typeofdefinefunctiondefine。amd?define(factory):(globaltypeofglobalThis!undefined?globalThis:globalself,global〔bundlename〕factory());})(this,(function(){usestrict;。。。。。代码省略。。。。。returnxxxxxxxx;}));
  可以看出导出的文件就是我们前面一直使用的函数自执行开发方式,其中加了各种兼容判断代码将在哪个环境下导入。2。es
  现代JS的标准,导出的文件只能使用ES模块化方式导入。3。cjs
  这个是指CommonJS规范导出的格式,只可在Node环境下导入。补充:模块化的发展早期利用函数自执行实现,在单独的函数作用域中执行代码(如JQuery)AMD:引入require。js编写模块化,引用依赖必须提前声明CMD:引入sea。js编写模块化,特点是可以动态引入依赖CommonJS:NodeJs中的模块化,只在服务端适用,是同步加载ESModules:ES6中新增的模块化,是目前的主流
  本文前三种插件编写方式均属于利用函数自执行(IIFE)实现的插件,同时在向全局注入插件时兼容了CommonJS规范,但并未兼容AMDCMD,是因为目前基本没有项目会使用到这两种模块化。自动化API文档
  一个JS插件如果没有一份文档,如同一台精密的仪器没有说明书。当别人使用你的插件时,他不可能去查看源码才知道这个插件有哪些方法、用途如何、要传哪些参数等。
  所以这里我们使用JSDoc来创建API文档,它使用简单,只需要在代码中编写规范的注释,即能根据注释自动生成文档,一举多得,十分优雅!npminstallsavedevjsdocopen
  修改package。json,增加一条脚本命令:。。。。。。。scripts:{。。。。。。doc:jsdocdistmain。es。jsnodeserver。js},
  根目录下创建文件server。js:varopenrequire(open);open(outindex。html);这是apidoc默认生成的路径,这里只是为了自动打开网页
  好了,现在可以使用npmrundoc命令来生成文档了,依然是举个栗子,我们在src目录下添加一个文件ArrayDelSome。js:desc对象数组去重param{Array}arrparam{String}对象中相同的关键字(如id)return{Array}返回新数组,eg:ArrayDelSome(〔{id:1},{id:2},{id:1}〕,id)返回:〔{id:1},{id:2}〕functionArrayDelSome(arr,key){constmapnewMap()returnarr。filter((x)!map。has(x〔key〕)map。set(x〔key〕,true))}exportdefaultArrayDelSome
  本例只演示最基础的用法,JSDoc有许多类型注释大家可以自行搜索学习下,不过本例最基本的这几个注释依旧是够用的。
  运行npmrundoc,将会打开一个网页,可以查看我们刚写的工具函数:
  注意:在生成文档前需要先进行过rollup的打包,且不能开启去注释之类的插件,因为上面的例子实际是对dist目录下的最终文件进行文档编译的。发布插件
  还没发布过npm包?限于篇幅就不展开,可以参考这篇文章如何发布npm包〔2〕。私有源发布
  如果你的公司有私域npm管理源,或者平时喜欢用淘宝源,推荐使用nrm进行切换:npminrmg1。查看源:nrmls2。添加源:nrmaddnamehttp:xxx。xxx。xxx。xxx:48733。删除源:nrmdelname4。使用指定源:nrmusenpm总结
  功能较简单的JS插件我们可以直接采用前三种方式开发,如果涉及DOM操作较多,可以编写仿JQ的插件更好用,如果插件功能较多,有可能形成长期维护的大型插件,那么可以采用工程化的方式开发,方便多人协作,配套生成文档也利于维护。
  以上就是文章的全部内容,希望对你有所帮助!如果觉得文章写得不错,可以点赞收藏,也欢迎关注,我会持续更新更多前端有用的知识与实用技巧,我是茶无味de一天〔3〕,希望与你共同成长引用链接
  〔1〕Rollup官网:https:rollupjs。orgguideen
  〔2〕如何发布npm包:https:juejin。cnpost6979531144043692039
  〔3〕关于作者:https:book。palxp。com

被微信替换的QQ被谁抛弃了?我和QQ的相见与离别30岁左右的年轻人,确实逐渐在抛弃QQ更准确说,这一大致年龄人群的社交被局限于微信朋友圈而20岁甚至年龄更小的年轻人,日常使用的即时聊天工具还是QQ除了QQ功能研究发现格陵兰岛迎来空前高温系1000年来最热最近一项基于最新冰芯数据的科学研究显示,与过去1000年重建的气候条件相比,格陵兰中部和北部的高温是前所未有的。在过去的十年里,来自阿尔弗雷德韦格纳研究所和尼尔斯玻尔研究所的研究人土叙大地震天边神秘闪光,美国HAARP项目险背锅愈来愈多的影片显示,在土叙大地震之前约几分钟,天边出现强烈的连续闪光,如同打雷闪电。在大地震之后人们开始回顾起这些诡异的闪光,有一种说法正在流传,认为是美国的HAARP天气实验,引48岁大哥喝酒21年,肝脏依然健康红润,医生酒后3件事做得好导语我们国家的酒文化可以说是源远流长的,随着时代的进步与发展,各种各样的酿酒技术更是应运而生,在众多的酿酒机器的相关运行之下,酒的种类也变得越来越多了。除了日常生活当中常见的啤酒白老虎在游客头顶漫步引热议!云南野生动物园回应来源春城晚报近日在云南野生动物园内一段老虎在游客头顶漫步的视频引发了热议借着玻璃通道边的一截枯木,一只虎妈妈一跃而上玻璃通道顶部,在上面悠闲地漫步。游客站在玻璃通道里,近距离地感受白菜是胃炎的发物?建议保养肠胃,这几种菜尽量要少吃目前,胃肠病在我国的发病率已经达到了20左右,也就是说两成的人会有肠胃疾病。特别是50岁以上的中老年人更为多见,而且该病呈现男性高于女性的发病特点。而胃病是靠治疗三分和保养七分,所颈肩腰腿痛,咱老百姓有验方三剑客发表于河北颈肩腰腿痛,咱老百姓有验方三剑客首先声明,以下用药为基础方,具体治疗需在当地医师望闻问切之后,开药,切记不可自行用药。1。三藤汤(鸡血藤海风藤络石藤)可通经入络,有祛风湿过量饮酒有害,饮酒多少算适量?一项超393万人研究结论健康2023酒精真是一个让人又爱又恨的东西。关于酒精的研究层出不穷,却一直没有定论。反常识的是,适量饮酒确实有好处!JAMANetworkOpen上最新发表的全国回顾性队列研究显示肿瘤专家12条防癌黄金法则,条条都是防癌金句,不妨照做,分享在医学上,癌是指起源于上皮组织的恶性肿瘤,是恶性肿瘤中最常见的一类。相对应的,起源于间叶组织的恶性肿瘤统称为肉瘤,有少数恶性肿瘤不按上述原则命名,如肾母细胞瘤恶性畸胎瘤等,一般人们体内有病,脚能看出吗?医生若出现某些异样,趁早就医常言道百病始于脚,人老脚先衰,养生先养脚,护足不畏老。脚底是打开全身健康的一道秘门,这里有66个穴位6条正经和3条奇经通过,它们与人体的各个器官均有关联。双脚又是离心脏最远的部位,初春茶叶怎么喝?老茶客2喝2不喝要知道,喝对受益多步入初春,天气就逐渐变得温暖起来,人们终于不用再承受冬天的寒冷了。不过,一起随春天而来的,还有困扰人们春困干燥。这个时候,茶叶可是解渴止乏,提神醒脑的绝佳利器。不过,初春喝茶可是有
老师在家长群里通报学生测验考试成绩并排名次,这好不好,有没有必要?老师会班上排名成绩,一般是让家长有个底,才好让你知道你孩子在班上的水平。如果,从不让你知道就坏了,因为,你不知大家考得怎么样,也不知孩子的成绩算好不好。如果,班上小学大家孩子都95欠下高利贷,无力偿还怎么办?一个正常人如果问欠了高利贷无力偿还该怎办,多数人会回答去死吧。是自已那就去公安局自首,反正是死不如协助人民警察把这群放高利贷的团伙全部除掉,免得他们再去害人,也许你还有一线生机。老遇到许多亳州蒙城的和利辛的老乡,为什么都说自己是阜阳人?第一,以前蒙城和利辛都属于原阜阳地区,行政区域属于亳州是属于政治区域划分。第二,利辛,蒙城和阜阳地区说话习惯,口音,饮食习惯和阜阳地区一样。和亳州差别很大。第三,利辛蒙城的人去阜阳怎样才能在淘宝上卖东西?方法很简单店铺认证通过之后,我们就可以去上传产品就可以卖东西了。别看这是个基础的操作,其实,有很多新手都还不知道该怎么上传产品,下面,我们来给大家详细介绍下上传产品的步骤。一怎么上受拐卖的人有多苦?一对没有生育能力的老夫妻。先是买了一个傻子做儿子,后来儿子长大后,又到外地人那里,买了一个女孩子给他当媳妇。受到非人的折磨后,那女孩疯了。我们村边有一个很穷的家庭,只有一间小瓦房,比如赌博等骗局,澳门当地的常见骗术有哪些?十赌九输庄家赢,是亘古不变的铁律。这就是澳门最大的骗术。1,轮盘,电脑控制定你输。电脑程序是人为设置的,就是设定好了,让你大概率输钱。2,牌局,发牌小姐让你输。一走进赌场,最吸引眼现在在实习stm32,linux软件工程师和stm32之间怎么抉择?谢谢邀请,作为一名嵌入式开发工程师,由我来回答这个问题。STM32软件工程师和linxu软件工程师,都是使用C语言进行程序开发,但linux可以分为linux驱动开发和linux应高级技师和技师可以应聘工程师吗?相当于工程师什么级别?技师和工程师是属于两个不同系列的资格,技师是属于职业技能水平资格,而工程师是属于专业技术职务任职资格。在我国,目前这两个资格使用比较多的是在事业单位。职业技能水平资格对于的是事业单老年公交乘车卡主要功能是为了照顾老年人还是为了促进公交的发展?从主观上看是给老年人们的一个福利待遇,关心老年人,使老年人乘车方便,想走哪里,用不着走路就能古去哪里。既方便又减少了一些乘车方面的额外开支,无形地增加了老人们的经济收入,使老年人们北京二环胡同里最穷的本地人有多穷?为什么会穷?北京二环以里穷人很多。历史上的崇文区(被老百姓称为穷人区)。当时营房地区的人很穷,因为营房是以前兵马用房。现在沒拆迁的平房还不少。靠工资是买不起商品房的。有的一家几口仍然住在小平房开一个水果蔬菜店大约需要多少钱?一线城市我觉得要二十多万吧!首先开个水果店,要选好地址,做好市场调查房租押一付三,首付要5万多,加上水电费每个月要1000,管理费500算5300元。这是没装修必须要花的钱装修的钱
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网