前端模块化总结

js模块化的发展:最早js是没有模块化概念的,为了防止命名空间被污染,采用的是命名空间的方式,随着前端的发展,commonJs在后端的实践思想被应用在前端,再往后就出现各种模块化标准例如:AMD/CMD/UMD,到如今出现的新标准es6 modulejs模块化不断演变,不断由复杂变的更好用。如下简单总结一个各个模块的特点。

1.命名空间(nameSpace)

在没有模块化思想的时候,都是通过命名空间防止对象被污染,通常格式类似这样库名.类别名.方法名,如代码所示

var nameSpace = {}
nameSpace.method = nameSpace.method || {}
nameSpace.method.init = function(){
//do somethings
}
nameSpace.method.done = function(){
//do somethings
}

nameSpace对象上如果有method对象就使用nameSpace.method对象,没有就新建一个空对象用来防止命名冲突或者被覆盖的问题。这种方式的弊端就是如果命名空间被覆盖了,也是没办法检测到的,而且在使用的时候要记住完整的对象方法名,在团队开发的时候大家要提前约定好各自要使用的方法名,类名来避免冲突,很不方便

2.commonJS

是一种服务端的模块化规范,规定一个文件为一个模块,模块内的变量,方法外界是无法访问的,通过module.exports暴露模块接口,然后通过require的方式来引入使用模块接口。commonJs是运行在nodeJS服务端的,通过require进来模块接口都是同步执行的,因为对服务端来说,这种require方式都是本地加载。
如下代码:

//news.js
const Controller = require('egg').Controller;
class NewsController extends Controller {
    async list() {
        const dataList = await this.other();
        this.ctx.body = {
            code:0,
            masg:'news list success',
            data:dataList
        };
    }
    async other() {
        return {
            list: [
                { id: 1, title: 'this is news 1', url: '/news/1' },
                { id: 2, title: 'this is news 2', url: '/news/2' }
            ]
        }
    }
}
module.exports = NewsController;

3.AMD规范(Async Module Definition 异步的模块定义)

用于浏览器端的js加载,使用define定义模块,使用require加载模块,代表库是RequireJS,这个库的特点就是所有的依赖都会被前置,提前执行,代码格式如下:

define(
  //模块名
  "alpha", 
   //依赖模块
  ["require", "exports", "beta"], 
    //导出模块
  function (require, exports, beta) {
       exports.verb = function() {
           return beta.verb();
           //Or:
           return require("beta").verb();
       }
   }
);

4.CMD规范(Common Module Definition 通用模块定义)

cmd也是遵循一个文件为一个模块,也是通过define来定义模块,通过require加载模块,代表库是seaJS。
与AMD的区别就是执行方式不一样,CMD是尽可能的懒执行,模块会被下载下来,直到使用的时候才会执行。
代码如下所示:

// 所有模块都通过 define 来定义
define(function(require, exports, module) {

  // 通过 require 引入依赖
  var $ = require('jquery');
  var Spinning = require('./spinning');

  // 通过 exports 对外提供接口
  exports.doSomething = ...

  // 或者通过 module.exports 提供整个接口
  module.exports = ...

});

5.UMD(Universal Module Definition )通用解决方案

提供前后端统一的解决方案,实现大一统,支持AMD,CMD两种规范,基本原理就是:判断是否支持AMD,判断是否支持CommonJS,如果都不支持,就定义成全局变量,挂在到window上。

//代码体是个自执行函数
(function (root, factory){
    if (typeof define === 'function' && define.amd){
        define([], factory);
    } else if (typeof exports === 'object') {
         module.exports = factory();
    } else {
          //需要被暴露出去的对象eventUtil
          root.eventUtil= factory();
    }
}(this, function () {
    return {};
}));

6.es6 module (EcmaScript Module)

es6 module也是一个文件就是一个模块,通过export暴露一个接口,通过import引入模块。模块打包现在最好用的就是webpack了。

//定义模块
//requistApi.js
export const getListUrl = 'news/list';
export const getListRequest = (url,params = {}) => {
     const promise = new Promise((resolve,reject) => {
           $.ajax({
               type: "GET",
               url: url,
               data: params,
               dataType: "json",
               success: function(data){
                   resolve(data);
                },
                error:function(){
                   reject();    
                }
            });
      });
      return promise;
}
//引入模块
//list.js
import { getListUrl, getListRequest } from 'requistApi.js'
.....
.....

你可能感兴趣的:(前端模块化总结)