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...
});

 

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

posted @ 2017-06-30 14:40  Red丶  阅读(196)  评论(0编辑  收藏  举报