RequireJS 用于 JavaScript 模块加载器 - 文章教程

RequireJS 用于 JavaScript 模块加载器

发布于 2020-02-09 字数 8213 浏览 1227 评论 0

RequireJS 是一个JavaScript模块加载器,在 ES6 出现之前,JS 不像其他语言同样拥有 模块 这一概念,于是为了支持 JS 模块化,出现了各种各样的语言工具,如 webpack,如 ReuqireJS 等。

RequireJS 用于 JavaScript 模块加载器

RequireJS 是一个非常小巧的 JavaScript 模块载入框架,是 AMD 规范最好的实现者之一。最新版本的 RequireJS 压缩后只有 14K,堪称非常轻量。它还同时可以和其他的框架协同工作,使用 RequireJS 可以提升前端代码质量。

为什么使用 RequireJS

模块化

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

不会阻塞页面

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

按需加载

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

使用 RequireJS

1、在 HTML 中引入 JS 文件

<script data-main="js/script/main" src="js/lib/require.js"></script>

require.js 可以通过 npm 下载,或者去官网下载,script 里有个 data-main 属性,require.js 会在加载完成以后通过回调方法去加载这 data-main 里面的 JS 文件,所以这个 JS 文件被加载的时候,RequireJS 已经加载执行完毕。

2、配置 main.js,这里主要介绍如何在 main.js 里引入 jquery

require.config({
    paths:{
        "jquery":'../lib/jquery.min'
    }
});
require(['jquery'], function($){
    ... 
    // 通过此方式引入jquery才能使用$
    // 接下来正常写jquery代码就好
})

require.config() 可以对模块的加载行为进行自定义,并把模块变为全局可使用的。require.config() 就写在主模块(main.js)的头部。参数就是一个对象,这个对象的paths属性指定各个模块的加载路径。

require( [ ] ,function( ){ } ) 是 require.js 的核心之一,它接受两个参数。第一个参数是一个数组,表示所依赖的模块,上例就是 [‘jquery’],第二个参数是一个回调函数,当前面指定的模块加载成功后,它将被调用。加载的模块会以参数形式传入该函数,从而在回调函数内部就可以使用这些模块。

既然第一个参数是数组,里面就可以有多个值:

require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){
   ...
});

require() 会异步加载每个模块,浏览器不会失去响应,它指定的回调函数,只有前面的模块都加载成功后,才会运行,解决了依赖性的问题。

define 和 require

在整个 require 中,主要的方法为:require 和 define

(1)define定义模块

函数方法:

define(id?, dependencies?, factory)

总共有三个参数:id 定义的模块名字,一般在 config 中会定义,dependencies 为需要的依赖模块,factory 为定义的模块。其中 factory 为必填,另外两个为非必填项。

根据上面的参数配置可以看出,define 总共分为两种,第一种为独立模块,不依赖其他模块。第二种为非独立模块,需要依赖其他模块。

注:define 定义的模块可以返回任何值,不限于对象。

独立模块

一种通过一个对象简易定义:

define({
    name: "aimee",
    method1: function() {},
    method2: function() {}
})

注:这样定义的对象如果被多处引用,那么引用的地方会共享这个对象的引用。

另一种通过一个函数来定义副本对象模块:

define(function () {
    //Do setup work here
    return {
        name: "aimee",
        method1: function() {},
        method2: function() {}
    }
})

这种自由度更高,可以在函数中处理其他逻辑。

非独立模块

需要引入依赖模块,在其他模块加载完,定义自己的模块,此时返回的method方法中包含模块1 和模块2的函数的调用。

define(['module1', 'module2'], function(m1, m2) {
    return {
        method: function() {
            m1.methodA();
            m2.methodB();
        }
    }
})

当定义多个时,可以通过 function 函数里接受一个 require 默认参数来处理。

define(
    [       'dep1', 'dep2', 'dep3', 'dep4', 'dep5', 'dep6', 'dep7', 'dep8'],
    function(dep1,   dep2,   dep3,   dep4,   dep5,   dep6,   dep7,   dep8){
        ...
    }
);

可以这样写

define(
    function (require) {
        var dep1 = require('dep1'),
            dep2 = require('dep2'),
            dep3 = require('dep3'),
            dep4 = require('dep4'),
            dep5 = require('dep5'),
            dep6 = require('dep6'),
            dep7 = require('dep7'),
            dep8 = require('dep8');

            ...
    }
})

(2)require 调用模块

通过 define 定义模块后,可以使用 require 来调用模块。

require(dependencies?, factory, errorCallback)

require 的参数有:dependencies 为依赖模块,非必填;factory 处理函数,必填;errorCallback 为 错误的回调,非必填;

require(
    ['foo', 'bar'], 
    function ( foo, bar ) {
        foo.doSomething();
        bar.doSomething();
    },
    function(err){
        console.log(err)
    }
);

上述例子,在 foo 和 bar 模块加载完成后,再在函数中执行 foo 和 bar 的方法,如果有错误则到错误的回调函数中,并接受一个error对象作为参数。

全局error事件监听,所有没有被上面的方法捕获的错误,都会被触发这个监听函数。

requirejs.onError = function (err) {
    // ...
};

define 中 require 异步加载

例子中,define 定义了一个模块,其中 foobar 需要依赖 foo 和bar 模块的方法,由于 require 为异步,此时 return 的结果可以通过 isReady 来判断是否加载完成。

define(function ( require ) {
    var isReady = false, foobar;
 
    require(['foo', 'bar'], function (foo, bar) {
        isReady = true;
        foobar = foo() + bar();
    });
 
    return {
        isReady: isReady,
        foobar: foobar
    };
});

可以用过 promise 来实现

define(function ( require ) {
    var obj;
 
    require(['foo', 'bar'], function (foo, bar) {
        isReady = true;
        obj.resolve({foobar:foo() + bar()});
    });
 
    return obj.promise()
});

上面代码返回一个 promise对象,可以在该对象的 then方法,指定下一步的动作。

小结
require 和 define 函数内部机制差不多,不一样的地方是 define 的回调函数需要有 return 语句返回模块对象,这样 define 定义的模块才能被其他模块引用;require 的回调函数不需要 return 语句。

requirejs config 配置

paths

可以配置模块的引用路径,可以本地相对路径,也可以是外部路径,可以提供多个路径,当第一个失败时,会使用第二个路径。
简单配置如下

require.config({
    paths: {
        jquery: [
            '//cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.min.js',
            'lib/jquery'
        ]
    }
});

baseUrl

baseUrl 指定了一个目录,然后requirejs基于这个目录来寻找依赖的模块。
可以通过config 来配置,也可以通过引入requirejs 文件的data-main属性定义。

shim

用于配置在脚本/模块外面并没有使用 RequireJS 的函数依赖并且初始化函数。假设 underscore 并没有使用 RequireJS 定义,但是你还是想通过 RequireJS 来使用它,那么你就需要在配置中把它定义为一个 shim。

<script src="js/require.js" data-main="js/main.js"></script>

或者

requirejs.config({
    baseUrl: 'js'
});

优化器 r.js

requireJS 提供一个基于 node.js 的命令行工具 r.js,用来压缩多个 js 文件。它的主要作用是将多个模块文件压缩合并成一个脚本文件,以减少网页的 HTTP 请求数。

相关链接

如果你对这篇文章有疑问,欢迎到本站 社区 发帖提问或使用手Q扫描下方二维码加群参与讨论,获取更多帮助。

扫码加入群聊

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

目前还没有任何评论,快来抢沙发吧!

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

2583 文章
29 评论
84935 人气
更多

推荐作者

清风夜微凉

文章 1 评论 0

为你鎻心

文章 2 评论 0

xxhui

文章 0 评论 0

1PKOH46yx8j0x

文章 0 评论 0

Arthur

文章 0 评论 0