美文网首页
js模块化

js模块化

作者: Ni_c746 | 来源:发表于2019-12-12 10:07 被阅读0次

    # js模块化

    **JavaScript本身是不支持模块化的,只不过后来一些社区的大佬制定了一个模块规范,主要分为两种,一个是用于服务器的CommonJs,另一种用于客户端的AMD(比如requireJs)、CMD(比如seaJs)。后来ES6提供了通用的模块化方案**

    ## 1.AMD(requireJs) 

    在ES6出现之前,JS不像其他语言同样拥有“模块”这一概念,于是为了支持JS模块化,出现了各种各样的语言工具,如ReuqireJS。 

    ``` 

    <!--require.html--> 

    <!DOCTYPE html> 

    <html> 

    <head> 

    <title>requirejs学习</title> 

    </head> 

    <body> 

    <script src='./js/require.js'></script> 

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

    <script> 

    require(['people'], function (people) { 

    people.say('Neol'); 

    }) 

    require(['cat'], function (people) { 

    people.say(); 

    }) 

    </script> 

    </body> 

    </html> 

    ``` 

    ``` 

    // ./js/config.js 

    require.config({ 

    //默认情况下从这个文件开始拉去取资源 

    baseUrl:'./js/', 

    path: { 

    'jquery': './js/jquery.js' 

    }); 

    ``` 

    ``` 

    // ./js/people.js 

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

    return { 

    say: function say(name){ 

    console.log('I am ' + name, $); 

    }); 

    ``` 

    ``` 

    // ./js/cat.js 

    define([], function() { 

    return { 

    say: function say(){ 

    console.log('喵喵喵~'); 

    }); 

    ``` 

    特点: 

    * js、jquery可以直接使用 

    ## 2.CMD(seaJs) 

    SeaJS 是一个适用于 Web 浏览器端的模块加载器。使用 SeaJS,可以更好地组织 JavaScript 代码。 

    ``` 

    <!--seajs.html--> 

    <!doctype html> 

    <html lang="en"> 

    <head> 

    <meta charset="UTF-8"/> 

    <title>seajs入门实例</title> 

    </head> 

    <body> 

    <div id="hello">132456798</div> 

    </body> 

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

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

    <script> 

    // 加载入口文件 

    seajs.use(['./js/hello'], function(hello) { 

    $('#hello').click(function(){ 

    hello() 

    }) 

    }); 

    </script> 

    </html> 

    ``` 

    ``` 

    // config.js 

    seajs.config({ 

    base: './js/', 

    path: { 

    'jquery': './js/jquery.js' 

    }); 

    ``` 

    ``` 

    // hello.js 

    define(function(require, exports, module) { 

    require('jquery'); 

    module.exports = function () { 

    $('#hello').toggle('slow'); 

    }); 

    ``` 

    特点: 

    * js、jquery可以直接使用

    ## 3.es6模块化 

    ``` 

    // 1.js 

    export const a = 1; 

    export const b = 2; 

    // 2.js 

    import {a, b} from './1.js'; 

    ``` 

    ``` 

    // 1.js 

    const a = 1; 

    const b = 2 

    export {a, b} 

    // 2.js 

    import {a, b} from './1.js'; 

    // 3.js 

    import * as obj from './1.js'; 

    ``` 

    ``` 

    // 1.js 

    const a = 1; 

    export default a; 

    // 2.js 

    import obj from './1.js'; 

    ``` 

    ``` 

    // 1.js 

    import('./2.js').then(res =>{ 

    console.log(res); 

    }); 

    ``` 

    特点: 

    * 每一个模块只加载一次, 每一个JS只执行一次, 如果下次再去加载同目录下同文件,直接从内存中读取。 一个模块就是一个单例,或者说就是一个对象; 

    * 每一个模块内声明的变量都是局部变量, 不会污染全局作用域; 

    * 模块内部的变量或者函数可以通过export导出; 

    * 一个模块可以导入别的模块 

    * export能有多个,但是export default只能有一个。 

    缺点:需要支持es6,或者使用babel.js转换。 

    结论:用在有webpack可以配置babel的项目,不用在jquery项目。

    ## 4.浏览器中的 ES6 module 实现

    ```

      <script type="module">

            import { alert_msg } from './utils.js'

            alert_msg('123456789')

        </script>

        // 使用 `nomodule` 属性向后兼容

        <script nomodule src="fallback.js"></script>

    ```

    ```

    // utils.js

    export function alert_msg (text) {

        alert(text)

    }

    ```

    特点:

    * 浏览器加载 ES6 模块,也使用`<script>`标签,但是要加入`type="module"`属性;type="module" 等同于打开了`<script>`标签的`defer`属性

    * 代码是在模块作用域之中运行,而不是在全局作用域运行。模块内部的顶层变量,外部不可见

    * 模块脚本自动采用严格模式,不管有没有声明`use strict`

    * 模块之中,可以使用`import`命令加载其他模块(`.js`后缀不可省略,需要提供绝对 URL 或相对 URL),也可以使用`export`命令输出对外接口

    * 模块之中,顶层的`this`关键字返回`undefined`,而不是指向`window`。也就是说,在模块顶层使用`this`关键字,是无意义的

    * 同一个模块如果加载多次,将只执行一次

    * 利用顶层的`this`等于`undefined`这个语法点,可以侦测当前代码是否在 ES6 模块之中

    缺点:兼容性不足

    ![image.png](./upload/201912/11/1576045913604281624.png)

    结论:不要用

    ## 5.CommonJS

    根据CommonJS规范,一个单独的文件就是一个模块。加载模块使用require方法,该方法读取一个文件并执行,最后返回文件内部的exports对象。所以,定义一个模块就是写一个新的js文件,但是最后要将文件的内容exports出来。接下来我们看一下如何定义模块和加载模块。

    ```

    //定义一个module.js文件 

    var A = function() { 

    console.log('我是定义的模块'); 

    //导出这个模块 

    //1.第一种返回方式 module.exports = A; 

    //2.第二种返回方式 module.exports.test = A 

    //3.第三种返回方式 exports.test = A; 

    exports.test = A; 

    //再写一个test.js文件,去调用刚才定义好的模块,这两个文件在同一个目录下 

    var module = require("./module");  //加载这个模块 

    //调用这个模块,不同的返回方式用不同的方式调用 

    //1.第一种调用方式 module(); 

    //2.第二种调用方式 module.test(); 

    //3.第三种调用方式 module.test(); 

    module.test(); 

    //接下来我们去执行这个文件,前提是你本地要安装node.js,不多说了,自己百度安装。 

    //首先打开cmd, cd到这两个文件所在的目录下,执行: node test.js 

    node test.js 

    //输出结果:我是定义的模块

    ```

    特点:

    * 模块化:模块化就是将不同功能的函数封装起来,并提供使用接口,他们彼此之间互不影响。 

    * 不会阻塞页面:RequireJS,会在相关的js加载后执行回调函数,这个过程是异步的,所以它不会阻塞页面。 

    * 按需加载:平时我们写html文件的时候,在底部可能会引用一堆js文件。在页面加载的时候,这些js也会全部加载。使用require.js就能避免此问题。举个例子,比如说我写了一个点击事件,放到了一个js文件里,并在html引用,在不使用require.js的情况下,页面加载它跟着加载,使用后则是什么时候触发点击事件,什么时候才会加载js。

    缺点:

    * 只能用在node服务端。

    [.zip](./upload/201912/11/15760622351371730206.zip)

    相关文章

      网友评论

          本文标题:js模块化

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