前端模块化
前言
前端开发领域发展到目前阶段:
-
零件化 - 最终呈现给用户是一个完整的产品(由各个零件组成的)
- 降低生产成本 – 多人协作(每个人各司其职)
- 降低使用成本 - 各个零件之间是低耦合的
-
组件化 - 将一个完整的产品划分成各个组件
- 前端开发中更多是指HTML页面和CSs样式
-
模块化 - 将一个完整的产品划分成各个模块
- 前端开发中更多是指JavaScript逻辑
-
组件化与模块化的关系
- 将一个完整的产品,划分成若干的组件
- 将每一个组件划分成若干的模块
-
组件化与模块化的特点
- 是低耦合的 - 软件开发的统一原则
- 是热插拔的 - 指的是需要时使用,不需要是去掉
前端模块化是什么
所谓模块化,就是指根据功能的不同进行划分,每个功能就是一个模块。最终,一个完整的产品是由各个模块组合而成的。
特点:
独立性
- 可以针对一个模块单独进行设计、研发,相对工作量和难度变小。复用性
- 一些通用模块(例如登录或注册)可以被重复使用,而不用每次重新开发。解耦性
- 模块与模块之间,将相互影响降到最低,使得更换、升级或添加某个模块,不影响其他模块的工作。灵活性
- 通过选择和组合不同的模块,可以快速构建一个新的产品。
ECMAScript 5的模块化
没有模块化概念
无模块化概念
函数的封装
函数的定义可以将代码逻辑封装在指定的函数作用域中
无法在全局作用域再定义一个outer()函数
对象的定义
使用对象实现的好处:
- 解决了全局命名空间可能出现的冲突问题。因为所有的模块成员都是作为一个对象的属性或方法存在的。
- 模块成员之间也存在着某种关系。因为被定义在同一个JavaScript对象中,作为属性或方法存在。而这个对象名成为了所有模块成员对外的一个统一的模块名称。
自调函数
看似引入对象概念后,这个模块的解决方案不错,但依旧存在着一些问题。对于这样一个模块(对象),是可以从外部对该模块(对象)的属性或方法进行修改的。这就导致了会产生一些意外的安全问题,而这个问题可以通过自调函数来进行解决。
最终模块化结构
var outer = (function (){
var v = 'longestory';
var interface ={
getAttr: function (){
return v;
},
inner: function (){
return 'this is inner function.";
}
}
return interface;
})();
ECMAScript 6的模块化
ECMAScript 6的模块化
-
ECMAScript 2015的模块
自动开启严格模式
,即使没有写use strict;. -
可以在模块中使用import和export命令。
export命令
export命令用于将指定的模块内容导出,该命令可以修饰在function、var、let或 const等之前。
export var v = 100;
export const c = 1000;
export let l = 'this is string.';
export function fn(){
return 'this is function.';
}
import命令
irmport命令用于导入其他模块所提供的功能,
import {...} from modulepath;
import {导出的名称 as 别名}from modulepath
使用import命令导入的名称必须与模块使用export 导出的名称一致。
使用 import命令导入其他模块的内容时,默认使用的是模块声明的名称。也可以在导入时,进行重命名。
前端模块化规范
- CommonJS
- RequireJS(AMD)
- SeaJS(CMD)
RequireJS
加载RequireJS
<script src = 'script/require.js' defer async='true'></script>
主模块的编写
<script data-main='scripts/main.js' src='scripts/teauire.js' defer async='true'></script>
定义模块
-
健值对方式定义
-
函数式定义
-
存在依赖的函数式定义
加载模块
- RequireJS使用config()函数对模块的加载行为进行自定义。
reauire.config({
paths: {
'jquery':''jquery.min',
'underscore': 'underscore.min',
'backbone': 'backbone.min'
}
};
- RequireJS使用require()函数来加载指定模块。
require(['jquery' , 'underscore', 'backbone'], function ($,_, Backbone) {
// some code here
});
SeaJS
加载SeaJS
<script src = 'script/sea.js' defer async='true'></script>
加载模块
- 利用config()方法进行配置
//seajs的简单配置
seajs.config({
base: '../sea-modules/',
alias: {
'jquery': 'jquery/jquery/1.10.1/jquery.js'
}
})
- 利用use()方法加载模块
//加载入口模块
seajs.use('../static/hello/src/main')
定义模块
- 利用define()方法定义模块
//所有模块都通过define来定义
define(function (require, exports, module){
//通过require 引入依赖
var $ = require('jquery');
var Spinning = require(''./spinning')
//通过exports对外提供接口
eports.doSomething= ...
//或者通过module.exports提供整个接口
module.exports = ...
});