什么是模块化?

以前我们可能会这样做代码分工

modules.js -----

var moduleA = {......}

var moduleB = {......}

var moduleC = {......}

然后每个页面都引入JS

<script src="modules.js"></script>

不管这个页面用到了几个模块,你都要把整个文件加载进来,于是我们就想,不如分开吧

然后我们的代码变成了这样:

moduleA.js -----

var moduleA = {......}

moduleB.js -----

var moduleB = {......}

moduleC.js -----

var moduleC = {......}

但是,由于各个模块之间存在相互引用的依赖关系,所以我们这样引入JS:

<script src="jquery.js"></script>

<script src="moduleB.js"></script>

<script src="moduleC.js"></script>

<script src="moduleA.js"></script>

假设A引用了C,而C引用了B,ABC里面都用到了JQ,你必须小心翼翼的确保它们的加载顺序是正确的

于是require.js出现了

按照requireJS当中的规范要求,你只需加载一个文件就可以,但同时需要带上一个配置文件config.js

第一步:

<script data-main ="config.js" src ="require.js"  ></script>

这个require.js你可以从官网下载,这个config.js你必须自己完成。不用担心,它写起来非常简单:

config.js -----

requirejs.config({

baseUrl : "js",

paths : {

"jquery": "jquery/jquery.1.11.3"

}

});

baseUrl的意思就是说你所有的路径都是基于它基础上的。

看的出来,我们正在配置一个文件的路径

"jquery": "jquery/jquery.1.11.3"

左边蓝色的是我们定义的模块名称,右边红色则是文件路径,注意文件没有后缀名,因为在require看来所有的模块都是JS

紧接着,我们可以定义自己的模块文件了,moduleB.js

首先mouduleB.js也是一个模块,但是我们必须对这个JS改造一下,让它符合require的规范要求,才能使用

moduleB.js -----

define(["jquery"],function(jq){

//根据我们之前的设定,模块B需要使用Jquery

//define函数中的第一个参数,用来表明,我们即将引用哪个模块。

//由于之前我们已经定义过了jquery模块,所以这里可以直接使用

//注意,你如果不写声明,这里是用不了jQuery的

//你如果注意到第一个参数是一个数组,那就应该猜到,其实我们可以一次引用好多模块

//jq变量就是jquery,你如果不习惯,把名字改回$就是了

return {

start: function(){

jq("#box").show(1000);

console.log("模块B提供的start方法");

//为什么这里要return呢? 因为我们定义的模块要被其他人使用

//那又为什么要return对象呢?为了更符合模块化思维以及面相对象的原则

//我们返回一个对象而不是函数,使用会更方便(待会讲完怎么调用你就知道了)

}

}

});

好了,模块B定义完了,我们可以来试试。当然,用之前别忘了修改配置

config.js -----

requirejs.config({

baseUrl : "js",

paths : {

"jquery": "jquery/jquery.1.11.3",

"moduleb" : "ms/moduleB"

}

});

注意:配置路径时,排名不分先后,顺序可以任意。

我们有一个index.html页面,包含一个index.js文件。

index.js -----

require(["config",function(){ //config默认从项目根目录找,由于我们的config.js就是放在根目录下的

//只有先引用config,才能引用配置好的所有模块

require(["jquery","moduleb"],function($,mb){

//我们引用两个模块jquery、moduleb

mb.start(); //mb就是我们刚才在模块B中返回的对象

})

})

根据我们一开始的设定(A引用了C,而C引用了B,ABC里面都用到了JQ )

和上面的讲解,你能否自己完成moduleC.js和moduleA.js?

moduleC.js -----

define(["moduleb","jquery"],function(mb,$){

return {

.......

}

});

moduleA.js -----

define(["modulec","jquery"],function(mc,$){

return {

.......

}

});

别忘了配置:

config.js -----

..............

paths: {

"jquery": "jquery/jquery.1.11.3",

"modulea" : "ms/moduleA",

"moduleb" : "ms/moduleB",

"modulec" : "ms/moduleC"

}

..............

一些问题:

问:加载配置文件的路径问题?

根据你目前的页面的业务JS文件的位置来决定,也就是说,复杂加载config的JS在哪里,路径就从哪里开始

例如index.js在根目录,config也在根目录:

require(["config"],function(){...});

例如index.js在js目录中,config在根目录

require(["../oncfig"], function(){...});

例如index.js在根目录中,config在js目录

require(["js/config", function(){...}];

问:是不是所有要加载的模块,都必须写define函数,为什么jquery就没写,一样可以加载?

谁说JQ没写呢?这是jquery的部分源代码。

......

if ( typeof define === "function" && define.amd ) {

define( "jquery", [], function() {

return jQuery;

});

}

......

所以,所有的JS都必须遵循require的规范,才能够正确的加载

问:我自己写了一大堆的工具函数,请问怎么加载?

首先,工具函数也可以用对象来表示

common.js -----

define(function(){

return {

getStyle : function(){ ........ },

randomColor : function(){ ......... }

}

});

当然如果你比较任性,非要写成这个样子:

common.js -----

function getStyle(){ ......... }

function randomColor(){ ........ }

解决办法也是有的:

请百度requireJS, shim配置

问:有一些插件,本身没有导出任何对象或核心函数,只是对某个框架的扩展,例如 my.jquery.scroll.js 该怎么用?

官方文档给出的答案是使用shim配置

config.js -----

require.config({

baseUrl: "js",

paths: {

"jquery" :  "jquery.1.11.3",

"jquery.scroll" : "my.jquery.scroll"

},

shim: {

"jquery.scroll": {

deps: ["jquery"],

exports: "jQuery.fn.scroll"

}

}

});

这是第一种方式, deps表示它依赖了哪个模块,exports表示它输出哪个函数,函数名字要和插件代码里保持一致

使用方式:

index.js -----

require(["config",function(){

require(["jquery","jquery.scroll"],function($){

$("#box").scroll(500);

})

})

=====================================================

第二种配置方式:

config.js -----

require.config({

baseUrl: "js",

paths: {

"jquery" :  "jquery.1.11.3",

"jquery.scroll" : "my.jquery.scroll"

},

shim: {

"jquery.scroll":  ["jquery"]

}

});

使用方法同上

But! 官方文档又说,这样使用可能导致错误! 请参考原文:

所以,终极解决方案是,把插件改成define调用.........

问:如果我用到了两个框架,Jquery和Zepto,他们的核心函数都叫$ ,那该怎么办呢?

require(["jquery","zepto"],function(jq,zepto){

// 改个名字就不冲突了

})

说一说好处:

讲了这么多,requirejs所倡导的模块化开发,好处在哪里呢?

1 你有没有发现,整个项目当中,再也没有出现一个全局变量?

2 你有没有发现,你再也没有考虑过加载顺序的问题?

3 你有没有发现,即使两个框架名字冲突了也没关系?

4 而且你肯定没有发现,所有的JS文件的加载过程,已经变成了异步。

5 最后,你还发现,用了requireJS,你的代码想不写成面相对象都难??

关于AMD和CMD

总在网上看大家讨论AMD和CMD,到底是什么东西呢?

AMD就是require所倡导的模块化开发的方式

还有一个叫CommonJS的,不过还是和requireJS有些区别,主要针对NODE后端开发

另外还有一个大名鼎鼎的SeaJS,作者是淘宝的玉伯,于是诞生了CMD规范

根据作者自己的介绍,SeaJS各方面都比requireJS强大

这个就不做评价了

至于区别呢?

AMD推崇的是依赖前置:

define(["a","b","c"],function(a,b,c){ //我们把所有依赖提前写好了

a.doSomething (); //这里直接使用

b.doSometing();

})

CMD推崇的是依赖就近:

define(function(require, exports, module) {

var a = require(‘./a‘);

a.doSomething();

.........

var b = require(‘./b‘) // 依赖可以就近书写,用到的时候再加载

b.doSomething()

})

当然requireJS也支持CMD的写法,不过作者本人是不推荐这么写的

时间: 2024-10-13 21:19:11

什么是模块化?的相关文章

可以将TCP BBR算法模块化到低版本内核取代锐速吗

上周的文章引发了比较火爆的争论并带来了争议,我比较满意或者遗憾,尽管如此,如果有人真的能明白在文章的背后我真正想表达的意思,我也就深感欣慰了.还像往常一样,我花周末的时间来总结结束,写点技术散文,同时我希望能在技术上引发同样的争论.        在跟温州皮鞋厂老板聊天时,老板让我从非技术角度重新思考了Google的BBR算法.        很多测试似乎表明BBR的表现非常不错,虽不能保证包打天下,至少相比锐速而言,它是免费的啊,那么疑问也就随之而来了,既然BBR是免费的,且效果不错,那么那些

从273二手车的M站点初探js模块化编程

前言 这几天在看273M站点时被他们的页面交互方式所吸引,他们的首页是采用三次加载+分页的方式.也就说分为大分页和小分页两种交互.大分页就是通过分页按钮来操作,小分页是通过下拉(向下滑动)时异步加载数据. 273这个M站点是产品推荐我看的.第一眼看这个产品时我就再想他们这个三次加载和翻页按钮的方式,那么小分页的pageIndex是怎么计算的.所以就顺便看了下源码. 提到看源码时用到了Chrome浏览器的格式化工具(还是朋友推荐我的,不过这个格式化按钮的确不明显,不会的话自行百度). 三次加载和分

C言语模块化开辟(多文件编程)

你好,欢迎离开「C言语模块化开辟」专题,在这里你将进修到大中型程序开辟技巧.本专题由C言语中文网站长执笔,将多年的编程经历灌注贯注个中,典型的理论派,你可以猛击<关于作者><若何才干完成这部教程>理解教程面前的故事.到今朝为止,我们编写的大局部C言语程序都只包括一个源文件,没有将代码疏散到多个模块中,关于只要几百行的小程序来说这或答应以承受,但关于动辄上万行的大中型程序,将一切代码都集中在一个源文件中几乎是一场灾害,后续浏览和保护都将称为顺手的成绩.在C言语中,我们可以将一个.c文

Selenium模块化

概述 高内聚低耦合是软件设计的一个基本原则. 内聚:从功能角度来度量模块内的联系,一个好的内聚模块应当恰好做一件事.它描述的是模块内的功能联系. 耦合:各模块之间相互连接的一种度量,耦合强弱取决于模块间接口的复杂程度.进入或访问一个模块的点以及通过接口的数据,模块之间联系越紧密,其耦合性就越强,模块的独立性则越差. 自动化测试模型也遵循上面的原则,下面从本人熟悉自动化测试的过程中来了解一下. 线性测试 先看两组脚本内容,实际应用过程中以百度进行示例 脚本1 from selenium impor

2.精通前端系列技术之JavaScript模块化开发

在使用seajs模块化开发之前,直接在页面引用js会容易出现冲突及依赖相关的问题,具体问题如下 问题1:多人开发脚本的时候容易产生冲突(比如全局参数冲突,方法名冲突),可以使用命名空间降低冲突,不能完全避免冲突 // JavaScript Document /*var a = 10; function tab(){} function drag(){} function dialog(){}*/ var miaov = {}; //名字比较长 , 只能降低冲突,不能完全避免 miaov.a =

UC前端‘搭积木’的模块化开发——scrat.js

模块化开发 将模块所需的js\css\img\tmpl维护在一起,一个模块一个目录 js渲染模板 css只关心模块内样式 开发团队心声:"我们希望每次研发新产品不是从零开始,不同团队不同项目之间能有可复用的模块沉淀下来." 模块生态 每个工程有_工程模块_和_生态模块_. 生态模块:基于_component规范_开发,部署到Github上,可以通过命令行工具将Github上的模块安装到工程中使用.比如:jQuery, iscroll, zepto.js, vue.js 安装命令: sc

关于Egret模块化开发---vip系统

关于Egret模块化开发---vip系统 目录 关于Egret模块化开发---vip系统... 1 前言... 1 一,搭建界面... 1 二,建立数据模型... 3 1)数据模型的搭建: 3 2)数据的建立... 4 3)数据的增删改查... 7 三.做交互, 7 结束... 8 前言 做游戏就是做数据,数据模型的设计,是体验mvc一种基础的设计,用数据驱动界面变化.. 做为一个程序要学会模块化,配置化,脚本化的需求,提防策划的需求变更的可能 例如:做一个VIP系统步骤: 搭建界面 建立数据模

前端模块化管理

转自网络 Task Runner Gulp.Grunt和Make(常见于c/cpp).Ant.Maven.Gradle(Java/Android).Rake.Thor(Ruby)一样,都是是Task Runner.用来将一些繁琐的task自动化并处理任务的依赖关系.其中有些是基于配置描述的,描述逻辑比较费劲,比如Ant基于xml.还有些就是代码,比较灵活,个人偏好这种.比如Rake.Thor.Gulp.Gradle.对于Gradle来说也有些蛋疼.因为它本身是Groovy的DSL.如果要深入使用

App 组件化/模块化之路——Android 框架组件(Android Architecture Components)使用指南

面对越来越复杂的 App 需求,Google 官方发布了Android 框架组件库(Android Architecture Components ).为开发者更好的开发 App 提供了非常好的样本.这个框架里的组件是配合 Android 组件生命周期的,所以它能够很好的规避组件生命周期管理的问题.今天我们就来看看这个库的使用. 通用的框架准则 官方建议在架构 App 的时候遵循以下两个准则: 关注分离 其中早期开发 App 最常见的做法是在 Activity 或者 Fragment 中写了大量

Javascript模块化编程(二):AMD规范

作者: 阮一峰 日期: 2012年10月30日 这个系列的第一部分介绍了Javascript模块的基本写法,今天介绍如何规范地使用模块. (接上文) 七.模块的规范 先想一想,为什么模块很重要? 因为有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块. 但是,这样做有一个前提,那就是大家必须以同样的方式编写模块,否则你有你的写法,我有我的写法,岂不是乱了套!考虑到Javascript模块现在还没有官方规范,这一点就更重要了. 目前,通行的Javascript模块规范共有两种