Web前端-JS-01-JS模块化规范

没有规矩,不成方圆,今天我们就来聊聊模块化规范

tmpdir__17_9_7_15_04_07.jpg

模块:对一些复杂的代码功能进行分离、按照某个规范进行封装成单个或者多个文件,同时暴露一些属性或者方法给外界调用。

为什么要模块化?
1.避免变量污染或者冲突
2.便于代码封装,提高复用性
3.代码便于维护,逻辑分离

温馨提示:文章结构如下,阅读完可能需要花费3分钟

一、模块化的进化过程
二、模块化规范之-CommonJS规范
三、模块化规范之-AMD规范
四、模块化规范之-CMD规范
五、模块化规范之-ES6规范

进入正文

一、模块化的进化过程

1.全局function模式 : 将不同的功能封装成不同的全局函数

优点:把单一功能封装在函数中,增加复用性
缺点:命名空间被污染,数据不安全,容易命名冲突

使用案例:

 function funcA() {
   console.log('函数A')
 }
function funcB() {
    console.log('函数B')
}
2.namespace模式: 命名空间,封装成对象

优点:减少全局变量
缺点: 数据不安全,可以直接修改内部变量

使用案例:

const module = {
message: "我是一个message",
run(){
       console.log('开始运行', this.message);
  },
};
module.message = "test";
module.run();
3.IIFE模式: 立即执行函数

优点:私有数据,外部只能访问暴露的方法或者属性
缺点:模块依赖其他模块比较麻烦

使用案例:

(function (window) {
    const url = "www.baidu.com";
    function run(){
        console.log('开始运行', this.url);
    };
    window.myModule = {run, url};
})(window);
myModule.run();

二、模块化规范之-CommonJS规范

同步加载,服务端文件一般存在本地,所以使用同步加载比较快,这个规范服务端常用

  1. CommonJS说明
    1.1.每个文件就是一个模块,有自己的作用域;
    1.2 每个文件里面定义的变量、函数、类,都是私有的;
    1.3.服务端-模块的加载是运行时同步加载;
    1.4.浏览器端-模块需要提前编译打包处理,才可以被运行
    1.5 运行时确定依赖关系
    1.6 CommonJS 模块输出的是一个值的拷贝

  2. 基本语法

导出方式一 : module.exports.xxxx = value

   const url = "www.zb.com";
   function funcA() {
      console.log('commonjs-导出-模块A',url);
   }
   //暴露属性
   module.exports.test = url;
   // 暴露方法
   module.exports.funcB = funcA;

导出方式二 : module.exports = {}

module.exports = {
   count: 4,
   addCount(){
        this.count++;
   },
   printB(){
        console.log('打印模块B');
   }
}

导入引用: require('路径引入或者第三方模块')

浏览器不能直接使用require,需要使用webpack 或者browserify 编译之后的文件浏览器才能识别

本质:加载某个模块,其实是加载该模块的module.exports属性

 const moduleA = require('./moduleA.js');
 const moduleB = require('./moduleB.js');
 console.log('打印模块A的属性',moduleA.test);
 moduleA.funcB();
 moduleB.printB();
 console.log('模块计算前的值',moduleB.count);
 moduleB.addCount();
 console.log('模块计算后的值',moduleB.count);

3.使用工具
browserify 或者 weback

三、模块化规范之-AMD规范

非同步加载,主要用于浏览器端

  1. AMD规范说明
    1.1 主要用于浏览器端,模块加载是异步的
    1.2 依赖于require.js

  2. 基本语法
    导出方式一 : 无依赖直接导出模块

    define(function () {
       const moduleA = {
        getMessage: function () {
         return "我是模块A的message";
      }
    }
       return moduleA;
    });
    

导出方式二 :有依赖导出

  define(['moduleA'], function (moduleA) {
  const moduleB = {
      getReuslt: function () {
          return moduleA.getMessage() + "我是模块B";
      },
  };
  return moduleB;
 });

引用模块

require(['moduleA','moduleB'], function (moduleA , moduleB) {
    moduleB.getReuslt();
})
  1. AMD + requirejs 使用

第一步: 下载require.js

下载方式 : 官网下载 或者 npm install requirejs --save-dev

第二步: 创建自定义模块, 目录如下moduleA, moduleB

image.png

第三步: 创建main.js 作为自定义模块的入口并配置

 // main.js
 (function () {
require.config({
    baseUrl: "./05-模块化规范/053-AMD规范",
    paths:{
        //映射: 模块标识名: 路径 不能加js
        moduleA: './moduleA', 
        moduleB: './moduleB'
    }
});
require('moduleB', function (moduleB) {
    moduleB.getReuslt();
})
})();

第四步:html中引用main.js 与requirejs

 <script src="../node_modules/requirejs/require.js" defer async="true"data-main="./053-AMD规范/main.js"></script>

defer async 表示异步 兼容写法
src: 引用requirejs
data-main: 模块入口

三、模块化规范之-CMD规范

  1. CMD规范说明
    1.1 commonjs + AMD 组合版
    1.2 主要用于浏览器
    1.3 模块的加载是异步的
    1.4 依赖于sea.js

  2. 基本语法

导出方式一:导出没有依赖的模块

define(function (require, exports, module) {
const moduleAA = {
    message: "我是模块AA",
};
module.exports = moduleAA;
});

导出方式二:导出有依赖的模块

define(function (require, exports, module) {
   const moduleAA = require('./moduleAA');
   const moduleBB = {
        printMessage:function () {
          console.log("我是模块BB" + moduleAA.message);
      },
};
  module.exports = moduleBB;
});

引入导入方式:define(function (require) {})

 define(function (require) {
const moduleBB = require('./moduleBB');
const moduleAA = require('./moduleAA');
// console.log('main文件打印---',moduleAA.message);
console.log('main文件打印---',moduleBB.printMessage());
});
  1. CMD+sea.js

第一步:下载或安装seajs npm install seajs --save-dev

第二步:新建自定义模块, 目录结构如下

image.png

第三步:新增main.js作为模块入口

// main.js
 define(function (require) {
const moduleBB = require('./moduleBB');
const moduleAA = require('./moduleAA');
// console.log('main文件打印---',moduleAA.message);
console.log('main文件打印---',moduleBB.printMessage());
});

第四步:html 使用模块

 <script  src="../node_modules/seajs/dist/sea.js"></script>
 <script type="text/javascript">
     seajs.use('./054-CMD规范/main');
 </script>

五、模块化规范之- ES6规范- 常用

  1. ES6规范说明
    1.1 编译时确定依赖关系
    1.2 ES6 模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块
    1.3 ES6 模块输出的是值的引用值

  2. 基本语法

导出

export default xxx 或者 export {}

导入

import

  1. 语法编译工具
    A. 使用Babel将ES6编译为ES5代码;
    B. 使用Browserify编译打包js