一、背景:
随着的互联网技术的不断发展,浏览器逐渐进化为集大成的CS客户端,页面功能向系统级、软件级靠拢的趋势下,开发团队也需要一些软件工程的方法来开发WEB项目,如测试驱动、面向对象,而模块化编程更是成为一种急需应用的技术。
全栈技术新Q群:435485569
二、需求:
为方便文件管理、增加复用,我们需要细化JS文件,每个文件负责一个职能,称之为模块,明确每个文件的职能,当交互功能较复杂时,引用的文件也越加庞大,此时我们就需要模块化管理。
如我们编写一个模块组件Dialog.js,但其依赖event.js / bootstrap.js / component.js,而event.js又依赖 base.js / core.js / el.js,bootstrap.js依赖 boot.js / under.js / almond.js,同理可能依赖更多的js,传统方法我们用到Dialog.js时实际上需要引用9个js,如下
<html> <body> ... <script src="/public/base.js"></script> <script src="/public/core.js"></script> <script src="/public/el.js"></script> <script src="/public/boot.js"></script> <script src="/public/under.js"></script> <script src="/public/almond.js"></script> <script src="/module/event.js"></script> <script src="/module/bootstrap.js"></script> <script src="/module/component.js"></script> <script src="/widget/dialog.js"></script> </body> </html>
我们将其细分,Dialog所依赖的每个js都负责了某一独立功能,分开便于其它组件复用,也利于学习理解。
但将这9个js都到html里显示引用,工作量却非常可观,且不能弄错路径及加载顺序,若后续Dialog.js又需要多引用一个js,所有的项目都要手动增加,且这样依次同步加载下来会导致会占用浏览器线程,可能导致假死。
模块化作用:
模块化的作用正是解决上面提到的两点问题。
1、实现js文件的异步加载,避免浏览器假死。
2、管理模块之间的依赖,便于模块的维护
三、模块化实现:
模块化,就是把一个相对独立的功能,单独成一个文件,可输入指定依赖、输出指定的函数,供外界调用,其它都是内部的。这样即可方便不同的项目重复使用,也不会对其造成额外的影响。而既然要给不同的项目应用,特别像git上的模块是面向全球范围的,必然要形成可遵循的规范,开发者和使用者都有据可寻。
目前通用javascript规范分为服务端(CommonJS),客户端(AMD / CMD)。
CommonJS是针对javascript的服务端,一切模块都是通过require来同步加载调用, Nodejs采用的就是这个规范。
var module1 = require( 'module1'), module2 = require( 'module2' ); function module3(){ } exports.module3 = module3;
注:通过require加载module1、2,操作后通过exports导致module3。
这里我们主要讲客户端模块
客户端与服务端的不同在于异步加载,之所以异步是因为CommonJS规则应用在服务端时,文件都是本地硬盘读取,不受限于网络,等待硬盘读取时间很短。而浏览器要考虑网速,若长时间等待会导致浏览器假死。
引用形式如下图
以前研究过sea.js某版本的源码,其原理就是将通过模块化加载的js,计算出其路径插入到 html.head里。
四、AMD。
是"Asynchronous Module Definition"的缩写,意思就是"异步模块定义",
以require.js为代表,官网http://requirejs.org/ ,其形式主要是
=============main.js=================== <script src="js/require.js" data-main="js/Dialog"></script> ==============Dialog.js======================= define( ['event', 'bootstrap', 'component' ], function( event, bootstrap, component ){ event.doSomthing(); bootstrap.doSomthing(); component.doSomthing(); var Dialog = function(){ ... } return { Dialog: Dialog } });
注:require接收两个参数,第一个参数是数组,含需加载的模块,第二个参数是回调,在模块加载成功后执行,且回调中的参数对应模块的加载顺序,这样主程序只需要加载一个JS文件,Dialog.js即可,其自会去加载event.js等文件,event.js再用同样的方式去加载base.js等,使用者无需考虑Dialog加载了多少引用,也无法担心其使用后会增减依赖。
五、CMD:以sea.js为代表,官网 http://seajs.org/docs/,理念为需要时再执行,即依赖就近
=============main.js=================== <script src="js/sea.js"></script> <script>seajs.use("../static/hello/src/main")</script> ==============Dialog.js======================= define( function( require, exports, module ){ var event = require( 'event' ); event.doSomthing(); var bootstrap = require( 'bootstrap' ); bootstrap.doSomthing(); var component = require( 'component' ); component.doSomthing(); var Dialog = function(){ ... } exports.Dialog = Dialog; })
注:模块引用本身就在回调里,并且在使用前引用即可,所以sea.js特别的是懒加载,这也就是AMD和CMD之间唯一的区别。实际上,require.js也支持CMD的写法,不过依赖前置是其官方推荐。我最初因为对国产和玉伯的支持敬佩,使用了seajs,近来为了弄清楚AMD,项目全部用了requirejs,虽然网上及seajs官方对两种逻列了一些分别,但使用下来,感觉并无优劣。
六、UMD
因服务端与客户端对模块化加载方式的不同,就会人想做一个兼容的模块UMD(Universal Module Definition),来解决跨平台的问题。但对于我们开发者来讲实则没有什么意义,也不深入了。
七、require.js详解:
require.config({ baseUrl: 'module/js', //配置path下的统一目的,以便path中不会分别配置 path: { //配置module路径,以便引用时不用写全路径 module1: 'module1', module2: 'module2', module3: 'http://www.site.com/module3' //若引用的是第三方,可以全部全路径 }, shim: { //对不符合AMD规则的模块引用 'underscore': { exports: '_' //配置其原对外接口 }, 'backbone': { deps: ['underscore', 'jquery'], //配置其依赖项 exports: 'Backbone' } } }); define( ['module1', 'module2' ], function( module1, module2 ){ module1.doSomthing(); module2.doSomthing(); function module3(){ ... } return { module3: module3 } });
八、require.js时间戳:
require.js没有找到可配置时间戳,可修改require.js源文件中的load方法
load: function (id, url) { url += '?' + timestamp; req.load(context, id, url); },
新增 url += '?' + timestamp; 这一处语句,即为url添加timestamp,timestamp可以另外通过配置文件配置。我使用nodejs开发,在服务端的config文件配置 timestamp: '2015091112',将其插入到客户端 ejs文件内
<script> var timestamp = '<%= timestamp %>'; </script>
这样即可在 require.js 文件内调用。
九、require.js合并:
官网提供了r.js用于该模块化的打包 https://github.com/jrburke/r.js http://requirejs.org/docs/download.html#rjs
r.js是将通过require.js引用的模块化文件都合并到一个文件里,以减少文件加载数量。
首先下载r.js,可以到静态文件根目录,新建build.js用于配置r.js,常见的配置如下
项目参考 https://github.com/xiaolulu/mynodejs.git
({ appDir: './', //项目根目录,给后面的baseUrl做参考;非必要项;默认为与r.js平级目录 dir: './min', //压缩后的文件的输出目录 baseUrl: './', //模块相对目录,与后面的paths配置使用 modules: [ { name:'login'}, { name: 'register' }, { name: 'center' } ], fileExclusionRegExp: /^(r|build)\.js|.*\.scss$/, //过滤文件不压缩 optimizeCss: 'standard', //css的标准方式 optimize: 'uglify', //设置是否压缩;uglify(压缩格式)|none(只合并不压缩) removeCombined: true, //设置移除压缩后的文件 paths: { //设置模块别名,方便引用,压缩后require.js引用的模块路径就在这里定义的,不是require.config里的 md5: 'core/js/md5', validate: 'widget/validate/validate', all: 'public/js/all', login: 'module/issue/login/login', register: 'module/issue/register/register', center: 'module/user/center/center' } });
执行 node r.js -o build.js
十、almond:
合并后所有原通过模块化加载的文件都已经在一个文件里了,已经不需要require.js的大部分功能,但因合并后代码里还是有require / define的函数定义,这里命令解析还是要有的,所以就有了almond.js(约15KB),其保留了require.js(约80KB)的子集,但不支持模块化加载,即对已经合并后的模块解析可以使用,减少代码量。
不过,其理念是好的,但实现方案还待改进,其执行后就会almond.js与前面合并后过的业务JS合并成一个文件,直接用 src来引用,意味着每个页面都需要的 almond.js将无法缓存,所以当业务JS超过五个时,这个方案将没有意义
相关推荐
在IT领域,分页、上传图片、MD5加密、验证码以及在线编辑器是常见的功能模块,它们在构建网站和Web应用程序时发挥着重要作用。以下是对这些知识点的详细说明: 1. **分页**:在处理大量数据时,分页是一种有效的...
总结,"pcli"是一个基于JavaScript和Node.js的CLI工具,很可能是一个开源项目,存储在一个Git仓库的主分支“master”下。这个工具可能包含了一系列实用的命令,用于提升开发者的生产力,而其具体功能和用法需要通过...
结构化程序设计强调的是清晰的逻辑结构和良好的可读性,主要包括三个核心原则:自顶向下(Top-down)、模块化(Modularization)以及逐步求精(Stepwise Refinement)。其中,“自顶向下”是指从整体考虑程序的设计...
pandas whl安装包,对应各个python版本和系统(具体看资源名字),找准自己对应的下载即可! 下载后解压出来是已.whl为后缀的安装包,进入终端,直接pip install pandas-xxx.whl即可,非常方便。 再也不用担心pip联网下载网络超时,各种安装不成功的问题。
基于java的大学生兼职信息系统答辩PPT.pptx
基于java的乐校园二手书交易管理系统答辩PPT.pptx
tornado-6.4-cp38-abi3-musllinux_1_1_i686.whl
Android Studio Ladybug 2024.2.1(android-studio-2024.2.1.10-mac.dmg)适用于macOS Intel系统,文件使用360压缩软件分割成两个压缩包,必须一起下载使用: part1: https://download.csdn.net/download/weixin_43800734/89954174 part2: https://download.csdn.net/download/weixin_43800734/89954175
有学生和教师两种角色 登录和注册模块 考场信息模块 考试信息模块 点我收藏 功能 监考安排模块 考场类型模块 系统公告模块 个人中心模块: 1、修改个人信息,可以上传图片 2、我的收藏列表 账号管理模块 服务模块 eclipse或者idea 均可以运行 jdk1.8 apache-maven-3.6 mysql5.7及以上 tomcat 8.0及以上版本
tornado-6.1b2-cp38-cp38-macosx_10_9_x86_64.whl
Android Studio Ladybug 2024.2.1(android-studio-2024.2.1.10-mac.dmg)适用于macOS Intel系统,文件使用360压缩软件分割成两个压缩包,必须一起下载使用: part1: https://download.csdn.net/download/weixin_43800734/89954174 part2: https://download.csdn.net/download/weixin_43800734/89954175
matlab
基于java的毕业生就业信息管理系统答辩PPT.pptx
随着高等教育的普及和毕业设计的日益重要,为了方便教师、学生和管理员进行毕业设计的选题和管理,我们开发了这款基于Web的毕业设计选题系统。 该系统主要包括教师管理、院系管理、学生管理等多个模块。在教师管理模块中,管理员可以新增、删除教师信息,并查看教师的详细资料,方便进行教师资源的分配和管理。院系管理模块则允许管理员对各个院系的信息进行管理和维护,确保信息的准确性和完整性。 学生管理模块是系统的核心之一,它提供了学生选题、任务书管理、开题报告管理、开题成绩管理等功能。学生可以在此模块中进行毕业设计的选题,并上传任务书和开题报告,管理员和教师则可以对学生的报告进行审阅和评分。 此外,系统还具备课题分类管理和课题信息管理功能,方便对毕业设计课题进行分类和归档,提高管理效率。在线留言功能则为学生、教师和管理员提供了一个交流互动的平台,可以就毕业设计相关问题进行讨论和解答。 整个系统设计简洁明了,操作便捷,大大提高了毕业设计的选题和管理效率,为高等教育的发展做出了积极贡献。
这个数据集来自世界卫生组织(WHO),包含了2000年至2015年期间193个国家的预期寿命和相关健康因素的数据。它提供了一个全面的视角,用于分析影响全球人口预期寿命的多种因素。数据集涵盖了从婴儿死亡率、GDP、BMI到免疫接种覆盖率等多个维度,为研究者提供了丰富的信息来探索和预测预期寿命。 该数据集的特点在于其跨国家的比较性,使得研究者能够识别出不同国家之间预期寿命的差异,并分析这些差异背后的原因。数据集包含22个特征列和2938行数据,涉及的变量被分为几个大类:免疫相关因素、死亡因素、经济因素和社会因素。这些数据不仅有助于了解全球健康趋势,还可以辅助制定公共卫生政策和社会福利计划。 数据集的处理包括对缺失值的处理、数据类型转换以及去重等步骤,以确保数据的准确性和可靠性。研究者可以使用这个数据集来探索如教育、健康习惯、生活方式等因素如何影响人们的寿命,以及不同国家的经济发展水平如何与预期寿命相关联。此外,数据集还可以用于预测模型的构建,通过回归分析等统计方法来预测预期寿命。 总的来说,这个数据集是研究全球健康和预期寿命变化的宝贵资源,它不仅提供了历史数据,还为未来的研究和政策制
基于微信小程序的高校毕业论文管理系统小程序答辩PPT.pptx
基于java的超市 Pos 收银管理系统答辩PPT.pptx
基于java的网上报名系统答辩PPT.pptx
基于java的网上书城答辩PPT.pptx
婚恋网站 SSM毕业设计 附带论文 启动教程:https://www.bilibili.com/video/BV1GK1iYyE2B