美文网首页
JS 模块化思想

JS 模块化思想

作者: 弱冠而不立 | 来源:发表于2020-09-19 21:22 被阅读0次

    模块化思想的出现

    不使用模块化的影响

    //对象问题
    var obj={
      name:'ming',
      age:20
    }
    //需求:我要修改对象的值
    obj.name='hong'
    

    如果这是一个公共类,公共的属性和方法,大家都去修改,谁想修改就去修改,这样就乱了,这样不合理,我们应该统一修改。
    一个公共类我应该是统一修改 或者是统一不修改。

    使用模块化思想优化

    // 创建一个 useModule.js文件
    const module = (function() {
        let obj = {
            name: "ming",
            age: 21
        }
    
        function setName(name) {
            obj.name = name;
            return obj.name;
        }
    
        function getName() {
            return obj.name;
        }
    
        return {
            setName,
            getName
        }
    })();
    
    // 按顺序导入 js  文件
     <script src="./useModule.js"></script>
     <script src="./index.js"></script>
    
    // 在 index.js 下直接使用
    console.log(module);
    console.log(module.getName());
    console.log("-------------");
    module.setName("hong");
    console.log(module.getName());
    
    这时候就有统一标准,谁调用或者修改这个代码就可以看到。

    模块和模块化的区别

    • 模块 : 是用于在项目中划分相对独立的功能,模块更偏重逻辑上区分
    • 模块化:是从代码逻辑的角度进行划分的,方便代码分层开发,保证每个功能模块的职能单一。

    模块化规范

    在模块化规范形成之前,JS开发者使用Module设计模式来解决JS全局作用域的污染问题。
    Module模式最初被定义为一种在传统软件工程中为类提供私有和公有封装的方法。
    在JavaScript中,Module模式使用匿名函数自调用 (闭包)来封装,通过自定义暴露行为来区分私有成员和公有成员。通过闭包的特性打开了一个新的作用域,缓解了全局作用域命名冲突和安全性的问题。但是,开发者并不能够用它来组织和拆分代码,于是乎便出现了以此为基石的模块化规范。

    CommonJs 规范

    CommonJS 是以在浏览器环境之外构建 JavaScript 生态系统为目标而产生的项目,比如在服务器和桌面环境中。

    目录结构
    |-modules
      |-module1.js
      |-module2.js
      |-module3.js
    |-app.js
    |-package.json
    
    基本语法
    • 模块暴露
    module.exports=value
    exports.xxx=value
    
    • 引入模块
    const module = require(xxx);
    //1.引入第三方模块时,xxx为模块名
    //2.引入自定义模块时,xxx为模块文件路径
    
    使用示例
    // module1.js
    let msg = "this is modules1";
    
    function getMsg() {
        return msg;
    }
    
    function setMsg(newMsg) {
        msg = newMsg;
        return msg;
    }
    
    module.exports = { getMsg, setMsg };
    
    // app.js
    const module1 = require("./modules/module1");
    
    console.log(module1.getMsg());
    console.log(module1.setMsg("this is app use module1"));
    
    运行 app.js 结果

    AMD 规范

    RequireJS是一个JavaScript文件或者模块的加载器。它可以提高JavaScript文件的加载速度,避免不必要的堵塞。它针对于在浏览器环境中使用做过专门的优化.

    目录结构

    将官网的 require.js 代码复制到 libs 下,然后就可以开始使用了

    |-js
      |-libs
        |-require.js
      |-modules
        |-module1.js
        |-module2.js
      |-main.js
    |-index.html
    
    基本语法
    • 暴露模块
    //没有依赖
    define(function(){
        return xxx
    })
    
    //有依赖
    define(['module1','module2'],function(m1,m2){
      return xxx
    })
    
    • 导入模块
    require(['module1','module2'],function(m1,m2){
      使用 m1/m2
    })
    
    • 路径配置
    //主入口文件(main.js)中配置
    require.config({
      //基本路径
      baseUrl: "js/",
      //模块标识名与模块路径映射
      paths: {
        "module1": "modules/module1",
        "module2": "modules/module2",
      }
    })
    //引入使用模块
    require( ['module1'], function(m1) {
      m1.xxx();
    })
    
    • 页面引入
    <script data-main="js/main" src="js/libs/require.js"></script>
    
    使用示例
    // module1.js
    define(function () {
        let msg = "this is modules1";
    
        function getMsg() {
            return msg;
        }
        return { getMsg }
    });
    
    // module2.js
    define(['module1',], function (m1) {
        let msg = m1.getMsg();
        function setMsg(newMsg) {
            msg = newMsg;
            return msg;
        }
        return { setMsg }
    });
    
    //main.js
    //主入口文件(main.js)中配置
    require.config({
        //基本路径
        baseUrl: "js/",
        //模块标识名与模块路径映射
        paths: {
          "module1": "modules/module1",
          "module2": "modules/module2",
        }
      })
      //引入使用模块
      require( ['module2'], function(m2) {
        console.log(m2.setMsg("hello"));
      })
    
    浏览器打开 index.html 的控制台输出

    ES6 规范

    ES6的模块规范 (ESModule)为了弥补 JS 没有模块系统 提出的优化方案。

    Node 环境中遵循的是 CommonJs 规范,并且浏览器方面为了要兼容低版本浏览器,所以要使用 babel 插件来编译 ES6 的代码。

    初始化项目并安装依赖
    npm init -y
    npm install babel-cli browserify -g
    npm install babel-preset-es2015 --save-dev
    
    创建.babelrc文件
    //根目录下创建,内容为
    {
       "presets": ["es2015"]
    }
    
    基本语法
    • 暴露模块
      • 分别暴露
      //module1.js
      export var msg = "this is module1";
      
      export function sayHello() {
        console.log("hello! this is module1");
      }
      
      • 统一暴露
      //module2.js
      var msg = "this is module2";
      
      function sayHello() {
        console.log("hello! this is module2");
      }
      
      export default {
        msg,
        sayHello
      }
      
    • 导入模块
    // app.js
    import { msg, sayHello } from "./modules/module1"; //分别暴露的导入方法
    import module2 from "./modules/module2";  //统一暴露的导入方法
    
    //直接使用分别暴露出来的变量和方法
    console.log(msg);  
    sayHello();
    
    //通过导入的对象,调用暴露的属性和方法
    console.log(module2.msg);
    console.log(module2.sayHello());
    
    使用姿势

    目录结构

    |-src
      |-modules
        |-module1.js
        |-module2.js
      |-app.js
    |-index.html
    |-.babelrc
    
    • node下
      安装好依赖后项目目录下运行:babel-node app.js

      node 环境下安装好插件依赖运行的结果
    • 浏览器环境下

    babel src -d src/build
    # -d左边的 src 是一个文件夹,因为所有文件都是用ES6的语法,需要全部转换为ES5。-d右边的src/build则是编译后的输出目录
    
    文件编译成功到指定文件位置

    此时,如果直接在index.html中运行<script type="text/javascript" src="js/build/main.js"></script>则会报错,因为其中包含require,浏览器不认识。所以我们还需要用browserify给转换一下。

    browserify src/build/app.js -o src/dist/bundle.js
    # -o 左侧的 build/app.js,是根据自己创建的根 js 文件名而来,例如你创建的根 js 是 main.js,经过第一步编译后的就是 src/build/main.js
    
    打包成功后项目目录如图所示

    在页面中引入打包好的bundle.js:

    <script src="./src/dist/bundle.js"></script>
    
    浏览器运行的结果

    相关文章

      网友评论

          本文标题:JS 模块化思想

          本文链接:https://www.haomeiwen.com/subject/otqeyktx.html