前端攻城狮Web前端之路前端开发那些事

require.js(初篇)

2017-02-06  本文已影响501人  范小饭_

由于没有找到官方文档,这里掺杂了很多笔者自己的理解写得,如果哪里有错,或哪位简友有官方文档,还请分享一下,谢谢~

一、关于模块化编程

1.1传统代码的缺陷

随着网站功能逐渐丰富,网页中的js也变得越来越复杂和臃肿。

原有通过script标签来导入一个个的js文件这种方式已经不能满足现在互联网开发模式,并且这样写有很大的 缺点,

首先,加载的时候,浏览器会停止网页的渲染,加载的文件越多,那么网页失去响应的时间越长,

其次,由于js文件之间存在依赖关系,因此必须严格保证加载顺序,依赖性大的模块一定要放在最后加载,当依赖关系很复杂的时候,代码的编写和维护都会非常困难。

所以我们需要团队协作、模块复用、单元测试等等一系列复杂的需求。

二、什么是模块化及模块化编程规范

模块化是只在处理某些问题的时候,按照一种分类思想对功能进行模块化的管理和使用。

2.1 require.js的诞生

require.js的诞生就是为了解决上述<script>加载问题。

AMD

require.js加载的模块,采用AMD规范。也就是说,模块必须按照AMD的规定来写。即需要用define()来定义模块和require(),后续会介绍如何定义模块

对于模块化的发展暂不做详细介绍,百度很6的~

2.2require.js的的加载

先去官网下载最新版本,下载后,可以选择把它放在文件的根目录下或者是js文件下
<script type="text/javascript" src="js/require.js" ></script>

为了避免加载文件的时候造成网页失去响应。解决办法有俩个,一个是把文件的加载放在网页的最底部,一个是写成下面这样
<script src="js/require.js" async="async" ></script>
async属性表明这个文件需要异步加载,避免网页加载的时候失去响应。

加载require.js之后,需要加载我们自己的js文件代码,假设我们自己的代码文件是app.js,也放在根目录下,那么就写成下面这样
<script type="text/javascript" src="js/require.js" data-main="app"></script>
data-main这个属性的作用是指定我们网页程序的主模块。这个文件会第一个被require.js加载。由于require.js默认的文件后缀名是js,所以可以把app.js简写成app。

2.3 主模块的写法

一旦我们定义了主模块的js文件,意思这个就是整个网页的入口代码,所有的代码都从这开始运行。

如果主模块代码不依赖于其他任何模块,那么可以直接写JavaScript代码。

这样就失去了require.js的意义了,因为正常情况下,主模块都会依赖于其他模块,这时就需要遵守AMD规范。

看栗子,格式像这样

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

require()函数
require()函数接受两个参数。
第一个参数是一个数组,表示程序所依赖的模块,即主模块依赖['moduleA', 'moduleB', 'moduleC']这三个模块;
第二个参数是一个回调函数,当前面指定的模块都加载成功后,它将被调用。加载的模块要以参数形式传入回调函数,从而在回调函数内部就可以使用这些模块。

举个栗子

require(["a","b","c"],function(A,B,C){
      .....something.....
})

此时各个模块之间的关系是这样的,index.html和app.js和modules文件架 在根目录下,modules文件下有moduleA,moduleB,moduleC三个文件夹,里边分别有a.js 和 b.js 和 c.js。

捕获.PNG

require.js会先加载'a', 'b', 'c',然后再运行回调函数。主模块的代码就写在回调函数中。

2.4模块的加载

上一节的栗子中,主模块的依赖模块是'a', 'b', 'c'
文件名分别为a.js ,b.js ,c.js 然后自动加载

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

栗子

//通过require.config方法来配置要导入的模块路径
require.config({
    paths:{
        //这里写要导入的路径和对应生成的模块名字
        a:"modules/moduleA/a",
        b:"modules/moduleB/b",
        c:"modules/moduleC/c"
    }
})

另注
1.如果模块在另一台主机上,也可以直接指定它的网址。
2.如果在这文件在同在其他弄一个文件夹内,比如都在lib文件架内,也可以指定baseUrl

2.5 AMD定义模块

AMD模块必须采用define()函数来定义

1.如果一个模块不依赖于其他模块,那么可以直接定义在define()函数中。

假设上栗中的a.js模块不依赖于其他模块,那么a.js中的代码如下

//define定义模块(不依赖于任何其他模块)
define(function () {
    //加法运算
    function add (x, y) {
        return x + y;
    }
    
    return {
        add : add
    }
})

2.定义模块的时候如果有依赖于其他模块的话,我们就可以把第一个参数加入,第一个参数是一个数组,数组中就是依赖模块的名字或者路径。

如果这里写路径,注意是相对于app.js而言的路径

假设上栗中的b.js是依赖于jquery和a.js模块的,那么我们可以在第一个参数中引入,代码如下

//定义模块的时候如果有依赖于其他模块的话,我们就可以把第一个参数加入
//第一个参数是一个数组,数组中就是依赖模块的名字或者路径
//如果这里写路径需要注意是相对于app.js而言的路径
define(['jquery', './modules/moduleA/a'], function ($, A) {
    //改变div颜色
    function changeColor () {
        $("#box").css({
                       //将div的北京变成蓝色
            backgroundColor : "red"
        });
    }
    
    //私有方法(说白了就是给自己用,不支持导出这个功能)
    //计算两数之差
    function mul (x, y) {
        return x - y;
    }
    
    function addAndMul (x, y) {
       //调用自身的两个函数
        changeColor();
        //用到了A模块里的功能和自身模块的私有方法
        return A.add(x, y) + mul(x, y);
    }
    //因为后续数据需要反馈,所以一定要return
    return {
        addAndMul : addAndMul
    }
    
});

当require()函数加载上面这个模块的时候,就会先加载他所依赖的模块。

3.为了方便理解下面内容,我们在c.js中也定义一个模块,其代码如下

define(['a', 'b'], function (A, B) {
    function changeColor () {
        $("#box").css({
            //将div的背景变成蓝色
            backgroundColor : 'blue'
        });
    }
    
    function fn (x, y) {
        changeColor();
        return  A.add(x, y) + B.addAndMul(x, y);
    }
    //因为后续数据需要反馈,所以一定要return
    return {
        fn : fn
    }
});

2.6 模块的调用

此时我们定义了了三个模块。分别为a.js 和b.js 和 c.js,并在主模块app.js中引入了三个模块。

此时我们需要调用这三个模块,并发挥他们的功能,因此,在app.js中,我么除了引入三个模块的路径,还需要调用,代码如下

//通过require方法来导入模块
//如果上面配置了路径,数组里导入的时候直接就可以写上面路径对应的模块名字即可
//jquery比较特殊,叫jquery以外其他名字的话,导出模块会是undefined
//注意:模块支持导出的话,一定要对应上,不支持导出的模块,我们放在数组中的最后
require(['jquery', 'a', 'b', './modules/moduleC/c'], function (j, A, B, C) {
    console.log($);
    console.log(j);
    //使用A模块的功能
    console.log(A.add(1, 2));
    //使用B模块的功能
    console.log(B.addAndMul(1, 2));
    //使用C模块的功能
    console.log(C.fn(1, 2));
});

调用了app.js需要依赖的a,b,c三个模块,又进行了引用,那么此时app.js中的全部代码如下

//通过require.config方法来配置要导入的模块路径
require.config({
    paths : {
        //这里写要导入的路径和对应生成的模块名字
        jquery : './lib/jquery',
        a : './modules/moduleA/a',
        b : './modules/moduleB/b'
    }
})

//通过require方法来导入模块
//如果上面配置了路径,数组里导入的时候直接就可以写上面路径对应的模块名字即可
//注意:模块支持导出的话,一定要对应上,不支持导出的模块,我们放在数组中的最后
require(['jquery', 'a', 'b', 'modules/moduleC/c'], function (j, A, B, C) {
    //使用A模块的功能
    console.log(A.add(1, 2));
    //使用B模块的功能
    console.log(B.addAndMul(1, 2));
    //使用C模块的功能
    console.log(C.fn(1, 2));
});

注意代码中c模块的变化了么?你再仔细瞅瞅?说好的引用呢?
温馨提示,也要注意b和c里面的代码哦

如果在配置依赖的模块路径没有配置,那么在require调用的时候,在数组参数中写其路径也是可以的。

主页面index.html中没有实际的内容,只是引用,代码如下

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title>
        <style type="text/css">
            #box{
                width: 200px;
                height: 200px;
                background-color: pink;
            }
        </style>
    </head>
    <body>
        <div id="box"></div>
        <!-- 导入requireJS库 -->
        <!-- data-main可以导入主入口文件app是指app.js -->
        <script type="text/javascript" src="lib/require.js" data-main="app"></script>
    </body>
</html>

此时运行index.html ** 注意 div的颜色。。**

运行结果(1).jpg

你觉得对么?按照加载的顺序,应该最后加载c.js div的颜色怎么是红色的?应该是蓝色的才对?

因为我们在c.js中return的时候,又调用了b.js,所以最后又加载了b.js,所以,div变成了红色~那么,如何解决这个问题呢?用变量存起来不就好啦 -,c.js中的代码如下

define(['a', 'b'], function (A, B) {
    function changeColor () {
        $("#box").css({
            backgroundColor : 'blue'
        });
    }
    
    function fn (x, y) {
        var num = A.add(x, y) + B.addAndMul(x, y);
        changeColor();
        return num;
    }
    
    return {
        fn : fn
    }
});
此时我们再输出一下结果
运行结果(2).jpg

此篇文章助大家理解require.js,真正的require.js用法,可没这么简单呢

不要吝啬赞美,喜欢就点赞啦

上一篇 下一篇

猜你喜欢

热点阅读