专题十四、requirejs

一、什么是requirejs

最早的时候,所有Javascript代码都写在一个文件里面,只要加载这一个文件就够了。后来,代码越来越多,一个文件不够了,必须分成多个文件,依次加载。下面的网页代码,相信很多人都见过。



这样的写法有很大的缺点。首先,加载的时候,浏览器会停止网页渲染,加载文件越多,网页失去响应的时间就会越长;其次,由于js文件之间存在依赖关系,因此必须严格保证加载顺序(比如上例的1.js要在2.js的前面),依赖性最大的模块一定要放到最后加载,当依赖关系很复杂的时候,代码的编写和维护都会变得困难。
require.js的诞生,就是为了解决这两个问题:
(1)实现js文件的异步加载,避免网页失去响应;
(2)管理模块之间的依赖性,便于代码的编写和维护。
RequireJS 是一个JavaScript模块加载器。它非常适合在浏览器中使用,但它也可以用在其他脚本环境, 就像 Rhino and Node. 使用RequireJS加载模块化脚本将提高代码的加载速度和质量。
使用RequireJS 的优点如下:
异步“加载”。我们知道,通常网站都会把script脚本的放在html的最后,这样就可以避免浏览器执行js带来的页面阻塞。使用RequireJS,会在相关的js加载后执行回调函数,这个过程是异步的,所以它不会阻塞页面。

按需加载。通过RequireJS,你可以在需要加载js逻辑的时候再加载对应 的js模块,这样避免了在初始化网页的时候发生大量的请求和数据传输,或许对于一些人来说,某些模块可能他根本就不需要,那就显得没有必要。

更加方便的模块依赖管理。相信你曾经一定遇到过因为script标签顺序问题而导致依赖关系发生错误,这个函数未定义,那个变量undefine之类的。通过RequireJS的机制,你能确保在所有的依赖模块都加载以后再执行相关的文件,所以可以起到依赖管理的作用。

更加高效的版本管理。想一想,如果你还是用的script脚本引入的方式来引入一个jQuery2.x的文件,然后你有100个页面都是这么引用的,那当你想换成jQuery3.x,那你就不得不去改这100个页面。但是如果你的requireJS有在config中做jQuery的path映射,那你只需要改一处地方即可。

二、requirejs使用步骤举例:

1)在页面引入如下文件

释义:文件可以建立如下图的结构

专题十四、requirejs_第1张图片
image.png

在页面引入require.js(require.js可以去官网下载也可以通过npm下载)
data-main:data-main属性的作用是,指定网页程序的主模块,即js入口文件。这里指的main.js,会在加载完require.js加载main.js
2)入口文件的写法
主模块依赖于其他模块,这时就要根据AMD定义的require()函数,写法如下:
requirejs(["helper/util","helper/topbar","helper/banner"], function(util,app,banner) {
// console.log('main开始执行了')
console.log(app)
var h = util.add(3,3)
var div = document.createElement('div')
div.innerHTML = h
document.body.appendChild(div)//

});
第一个参数是数组,包含依赖的模块js文件路径,后面是相应的回调函数。异步执行的,只有前面都加载完毕,后面的回调函数才会执行。里面是自定义的代码
require.config:我们可以通过在main.js加入require.config来统一指定模块加载的路径(默认路径是和main.js在一个目录),如:
 require.config({
    paths: {
      "jquery": "jquery.min",
      "underscore": "underscore.min",
      "backbone": "backbone.min"
    }
  });
当然,如果这些文件都有相同的基础路径,可以简写如下:
 require.config({
    baseUrl: "js/lib",
    paths: {
      "jquery": "jquery.min",
      "underscore": "underscore.min",
      "backbone": "backbone.min"
    }
  });
baseUrl就是这些文件的基础路径。当然文件如果在另一台主机上,可以指定它的网址

三、AMD模块的写法

入口文件写好,接下来就来写各个被依赖的模块。这些模块都是通过define()函数来定义的。分为两种:
1)本身不再依赖其他模块
define(function () {
console.log('topbar开始执行了')
var app = function (){
nide
}
return app
});
2)依赖其他模块
define(['./ppou'],function (math) {
console.log('banner开始执行了')
console.log(math)
});
如果还依赖其他模块,第一个参数就是数组,里面是模块路径。
tips:这里想说下模块与模块之间的变量交互,情况如下信息:
*define(['./ppou'],function (math) {
console.log('topbar开始执行了')
console.log(math)
});
这是topbar文件内容,可以看到它依赖于ppou文件
define(function () {
console.log('ppou开始执行了')
function plugin(){
}
return plugin
});
这是ppou文件内容
释义:ppou文件整体可以看做是个对象,而topbar里function里的参数math就是这个对象的返回值,这里也就是plugin,所以输入是: function plugin(){
}。但是需要注意的是,如果我的ppou文件写法如下:

define(function () {
console.log('ppou开始执行了')
function plugin(){
}
return {
plugin:plugin
}
});
要想得到如上的效果,你需要在topbar里这样写:
*define(['./ppou'],function (math) {
console.log('topbar开始执行了')
console.log(math.plugin)
});
我的理解是相当于此时plugin成为了对象下面的属性了
相似的例子如下:

define(function (){
    var add = function (x,y){
      return x+y;
    };
    return {
      add: add
    };
  });
调用:
  require(['math'], function (math){
    alert(math.add(1,1));
  });


参考资料:
后台小白前端入门--RequireJS
Javascript模块化编程(三):require.js的用法

你可能感兴趣的:(专题十四、requirejs)