Board logo

标题: 使用 RequireJS 优化 Web 应用前端 (2)实战 RequireJS [打印本页]

作者: look_w    时间: 2018-10-17 19:02     标题: 使用 RequireJS 优化 Web 应用前端 (2)实战 RequireJS

实战 RequireJS在 Web 应用中使用 RequireJS在 RequireJS 官方主页上下载最新的版本的 require.js,放到 Web 页面中。示例的 Web 项目结构图 1 所示。
图 1. Web 项目结构通过在 index.html 中加入一个 <script> 标签直接引入 require.js 即可。
RequireJS 功能初探RequireJS 使用起来非常的简单,但是这些功能确是在 Web 前端开发中非常重要的,下面我们来逐一看看如何使用 RequireJS 的各项功能。
使用 RequireJS 加载 JavaScript 文件
即使您的 Web 前端由于种种历史原因还没有打算进行模块化的设计,RequireJS 作为 JavaScript 文件的加载器,还是可以帮助您来完成异步非阻塞的文件加载。
如清单 2 所示,有两个 JavaScript 文件 a.js 和 b.js,里面各自定义了 myFunctionA 和 myFunctionB 两个方法,通过下面这个方式可以用 RequireJS 来加载这两个文件,在 function 部分的代码可以引用这两个文件里的方法。
清单 2. 加载 JavaScript 文件
1
2
3
4
5
6
7
<script src="./js/require.js"></script>
    <script>
   require(["./js/a.js", "./js/b.js"], function() {
            myFunctionA();
            myFunctionB();
       });
    </script>




require 方法里的这个字符串数组参数可以允许不同的值,当字符串是以”.js”结尾,或者以”/”开头,或者就是一个 URL 时,RequireJS 会认为用户是在直接加载一个 JavaScript 文件,否则,当字符串是类似”my/module”的时候,它会认为这是一个模块,并且会以用户配置的 baseUrl 和 paths 来加载相应的模块所在的 JavaScript 文件。配置的部分会在稍后详细介绍。
这里要指出的是,RequireJS 默认情况下并没有保证 myFunctionA 和 myFunctionB 一定是在页面加载完成以后执行的,在有需要保证页面加载以后执行脚本时,RequireJS 提供了一个独立的 domReady 模块,需要去 RequireJS 官方网站下载这个模块,它并没有包含在 RequireJS 中。有了 domReady 模块,清单 2 的代码稍做修改加上对 domReady 的依赖就可以了。
清单 3. 页面加载后执行 JavaScript
1
2
3
4
5
6
7
<script src="./js/require.js"></script>
    <script>
   require(["domReady!", "./js/a.js", "./js/b.js"], function() {
            myFunctionA();
            myFunctionB();
       });
    </script>




执行清单 3 的代码后,通过 Firebug 可以看到 RequireJS 会在当前的页面上插入为 a.js 和 b.js 分别声明了一个 <script> 标签,用于异步方式下载 JavaScript 文件。async 属性目前绝大部分浏览器已经支持,它表明了这个 <script> 标签中的 js 文件不会阻塞其他页面内容的下载。
清单 4. RequireJS 插入的 <script>
1
2
<script type="text/javascript" charset="utf-8" async="" data-requirecontext="_"
data-requiremodule="js/a.js" src="js/a.js"></script>




使用 RequireJS 来定义 JavaScript 模块
这里的 JavaScript 模块与传统的 JavaScript 代码不一样的地方在于它无须访问全局的变量。模块化的设计使得 JavaScript 代码在需要访问”全局变量”的时候,都可以通过依赖关系,把这些”全局变量”作为参数传递到模块的实现体里,在实现中就避免了访问或者声明全局的变量或者函数,有效的避免大量而且复杂的命名空间管理。
如同 CommonJS 的 AMD 规范所述,定义 JavaScript 模块是通过 define 方法来实现的。
下面我们先来看一个简单的例子,这个例子通过定义一个 student 模块和一个 class 模块,在主程序中实现创建 student 对象并将 student 对象放到 class 中去。
清单 5. student 模块,student.js
1
2
3
4
5
6
7
8
9
10
define(function(){
    return {
       createStudent: function(name, gender){
            return {
                name: name,
                gender: gender
            };
       }
    };
});




清单 6. class 模块,class.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
define(function() {
var allStudents = [];
       return {
           classID: "001",
           department: "computer",
           addToClass: function(student) {
           allStudents.push(student);
           },
           getClassSize: function() {
           return allStudents.length;
           }
       };
    }
);




清单 7. 主程序
1
2
3
4
5
require(["js/student", "js/class"], function(student, clz) {
clz.addToClass(student.createStudent("Jack", "male"));
clz.addToClass(student.createStudent("Rose", "female"));
console.log(clz.getClassSize());  // 输出 2
});




student 模块和 class 模块都是独立的模块,下面我们再定义一个新的模块,这个模块依赖 student 和 class 模块,这样主程序部分的逻辑也可以包装进去了。
清单 8. 依赖 student 和 class 模块的 manager 模块,manager.js
1
2
3
4
5
6
7
8
9
10
define(["js/student", "js/class"], function(student, clz){
return {
   addNewStudent: function(name, gender){
   clz.addToClass(student.createStudent(name, gender));
       },
   getMyClassSize: function(){
   return clz.getClassSize();
   }
    };
});




清单 9. 新的主程序
1
2
3
4
5
require(["js/manager"], function(manager) {
manager.addNewStudent("Jack", "male");
manager.addNewStudent("Rose", "female");
console.log(manager.getMyClassSize());// 输出 2
});




通过上面的代码示例,我们已经清楚的了解了如何写一个模块,这个模块如何被使用,模块间的依赖关系如何定义。还是有一些使用技巧需要提示一下:





欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0