• require.js 模块化


    什么是模块化?

    • 将若干功能进行封装,以备将来被重复使用。

    为什么要前端模块化?

    • 将公共功能进行封装实现复用
    • 灵活解决依赖
    • 解决全局变量污染

    如何实现前端模块化?

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>Document</title>
    </head>
    <body>
        <!-- 通过标签加载js是不能做到模块化的 -->
        <script src="./js/jquery.min.js"></script>
        <script src="./js/a.js"></script>
        <script src="./js/b.js"></script>
    </body>
    </html>

    Javascript 语言本身是不具备模块化能力的,需要自已进行封装来实现模块的定义以及加载,其实现遵照一定的规范(COMMONJS)

    Nodejs 是运行在服务端的Javascript,它是按着commonjs的规范实现的模块化

    经过实践发现浏览器端Javascript按着commonjs的规范实现模块化时,有很不足之处,此时就有人在commonjs的基础上重新定了一个规范AMD(Async Module Define),其代表就是require.js

    随前端开发演变,又有人定义另外一个浏览器端模块化的规范CMD(Common Module Define),淘宝的玉伯定义的,其代表是seajs

    前端模块化使用requirejs

    • requirejs 本身是一个js文件,它按照AMD规范实来实现模块的定义和加载规则,应用在浏览器端。

    定义模块

      模块是以文件形式存在的(一个文件对应一个模块也可以一个文件对应多个模块),通过define()方法来定义一个模块。

    • 基本定义
    define(function () {
            // 回调函数中即模块逻辑
            var str = 'a';
            alert(str);
            // code....
        });
    • 依赖注入(解决依赖的一种方式)
    // 通过一个数组来声明,模块的依赖
    define(['./a'], function (a) {
    
        var str = 'b';
        // 通过形式参数a来接收a模块的返回值
    
        // a模块返回值(对象)包含了方法now
        a.now();
        // a模块返回值(对象)包含了方法sayHi
        a.sayHi(a.name);
    
        console.log(str);
    
        // code....
    });
    • 返回值

      定义模块时,可以有返回值,但并不是必须,返回数据类型没有任何约束,通常返回值是对象更有意义。

    define(function () {
        // 回调函数中即模块逻辑
        var str = 'a';
    
        // console.log(str);
    
        // 直接返回字符串
        // return str;
    
        // 还可以是一个函数
        // return function () {
        //  console.log('现在是' + new Date);
        // }
    
        // 也可以是一个对象
        return {
            name: '小明',
            sayHi: function (name) {
                console.log('你好' + name);
            },
            now: function () {
                console.log('现在是' + new Date);
            }
        }
    
        // 返回值可以是任意类型,对象更有意义
    
        // code....
    });

    加载模块

       通过 require() 或者 requirejs() 方法来加载一个模块

    • 基本使用
        <!-- 引入requirejs -->
        <script src="./libs/require.js"></script>
        <script>
            // 加载模块
            // 同时加载两个模块,执行顺序与书写顺序无关
            require(['./a', './b']);
        </script>
    • 加载有依赖的模块
     <!-- 引入requirejs -->
        <script src="./libs/require.js"></script>
        <script>
            // 加载模块
            // b和c模块同时依赖了a模块
            // 当加载b和c模块时,a模块可以自动被加载进来
            require(['./b', './c']);
        </script>
    • 依赖注入
        <script>
    
            require(['./a'], function (a) {
                console.log(a);
    
                a.sayHi(a.name)
                a.now();
            });
        </script>

    入口文件

    •   通过为引入require的标签加入 data-main 属性,其属性值为某一个模块的路径,此模块可以自动被加载并执行。
        <!-- 使用自定义属性指定的模块,称为入口文件 -->
        <!-- 此文件会自动被执行 -->
        <script src="./libs/require.js" data-main="./index.js"></script>

    加载路径

     requirejs加载模块时,路径是遵照一些规则的,分成以下几种情况

    1. 当没有入口文件时,加载路径以引入requirejs的页面为准
    2. 当存在入口文件时,加载路径以入口文件所在目录为准
    3. 通过配置可以自定义加载路径
        <h2>配置requirejs的的路径</h2>
        <script src="./libs/require.js" data-main="./main.js"></script>
        <script>
            // 相对于当前页面
            // require(['./src/a']);
    
            // 假如使用入口文件,
            // 路径参照的是入口文件所在的目录
            // require(['./src/src/a']);
        </script>

    配置项

    • 配置基础路径
    // 通过config方法可以对requirejs进行配置
      // 其中通过baseUrl来配置加载路径
      require.config({
          baseUrl: './public'
      });
    • 配置路径

       通过path属性可以配置模块真实路径(baseUrl + path),这样配置后可以使得路径调整变的灵活。

    // 通过config方法可以对requirejs进行配置
        // 其中通过baseUrl来配置加载路径
        require.config({
            baseUrl: './public',
            // 使用path可以为模块真实路径起个"别名"
            paths: {
                jquery: 'assets/jquery/jquery.min'
            }
        });
    
        // a和b模块都依赖于jquery,当改变jquery路径时
        // 只需要改变配置里的path就可以了
        require(['./src/a', 'src/b']);
    • 配置不支持模块的插件

      在现实开发中并不是所有的JS库都是按着模块化形式开发,但是我们又不得不使用这些JS库,requirejs提供了解决方案。

    为了帮助理解,总结了模块的两个特点“舍与得”

         a) “舍”指模块将自身模块的功能提供给其它模块使用

        define(function () {
            var obj = {
                name: '小明',
                sayHi: function () {
                    //code...
                },
                now: function () {
                    // code...
                }
            }
            // 将自身功能提供给其它模块
            return obj;
        })

    b) “得”指模块将其它模块提供的功能直接拿来用

        define(['demo'], function (demo) {
            // 通过数组形式提定依赖的模块
            // 以形参的形式使用其它模块提供的功能
        });

    对于非模块requirejs也有解决方案,通过另外一种形式来满足“舍与得”的特点,如下

        // 通过config方法可以对requirejs进行配置
        // 其中通过baseUrl来配置加载路径
        require.config({
            baseUrl: './public',
            // 使用path可以为模块真实路径起个"别名"
            paths: {
                jquery: 'assets/jquery/jquery.min',
                c: 'src/c',
                demo: 'assets/custom/demo'
            },
            shim: {
                c: {
                    // 指定当前c模块依赖于demo
                    // 相当于标准模块里的
                    // define(['demo'], function () {});
                    deps: ['demo'],
                    exports: 'newobj'
                },
                demo: {
                    // 指明当前demo模块的返回值
                    // 相当于标准模块里的
                    // define(function () {return obj;});
                    exports: 'obj'
                }
            }
        });
    
        // require(['./src/a', 'src/b', 'c']);
        require(['c']);

    匿名模块和具名模块

    // 匿名
    define([], function () {
      // code...
      // return 
    });
    
    // 具名
    define('demo', [], function () {
      // code...
    });

    先写到这里吧,有机会再补充

  • 相关阅读:
    Codeforces Round #365 Div.2
    Codeforces Round #363 Div.2[111110]
    花花的礼物 (huahua)
    FOI2019算法冬令营D1
    树(tree)
    noip2018
    1972: 最短路(shortest)
    2462: 收集(collecting)
    1282: 排列计数 perm
    1425: 数列(seq)
  • 原文地址:https://www.cnblogs.com/bfc0517/p/7098752.html
Copyright © 2020-2023  润新知