js框架require.js使用入门教程

require.js简介

RequireJS是一个工具库,主要用于客户端的模块管理。它可以让客户端的代码分成一个个模块,实现异步或动态加载,从而提高代码的性能和可维护性。它的模块管理遵守AMD规范,模块与模块之间可以互相依赖,当然可能会有人会想,模块之间的依赖,要是没法正确地去按照特定顺序加载,会出现错误,AMD规范可以处理这种问题,AMD就是这样一种对模块的定义,使模块和它的依赖可以被异步的加载,但又按照正确的顺序。

AMD是"Asynchronous Module Definition"的缩写,意思就是"异步模块定义"。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。

如何使用require.js?

将require.js下载下来,嵌入网页中,

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

这里的data-main属性声明的是入口文件scripts/main.js,这里我们把.js后缀省略掉了。也有以下这种写法:

<script src="scripts/require.js" data-main="scripts/main" defer async="true" ></script>

async属性表明这个文件需要异步加载,避免网页失去响应。IE不支持这个属性,只支持defer,所以把defer也写上。同时,官方提供了 require.js和 jquery 的打包版本,于是也可以怎么引入:

<script src="scripts/require-jquery.js" data-main="scripts/main" defer async="true" ></script>

RequireJS通过define方法,将代码定义为模块;通过require方法,实现代码的模块加载。

使用define方法,可以将代码写在一个js文件,独立开来作为一个模块,如我建立一个animate模块(animate.js),如下:

define(function(){
  function animate(){
    this.name="animate";
  };
  return {
    animate:animate ,
    dec:"这是一个描述"
  };
})

将你的模块代码放置在define(function(){  /*代码*/   });,然后将该模块return的对象暴露出来,可以供其他模块依赖此模块的时候,可以去调用这个模块的API。比如我们建立一个tabview模块(tabview.js)去依赖这个animate模块,

define(['animate'],function(a){
    function tabview(){
        this.name= 'tabview';
        this.animate = a.animate.name;
        this.dec = a.dec;
    }
    return { tabview:tabview };
})

分析上面的代码,我们将animate模块引入,并给其赋予一个a的别名。那么在该模块不就可以调用animate模块里面的方法和属性了吗?

这里我们在多建一个treeview模块(treeview.js),如下:

define(function(){
    function treeview(){
        this.name="treeview";
    };
    return { treeview:treeview };
})

接下来,我们需要去使用前面我们定义好的模块,便可以require方法来实现,见其写在main.js中,如下:

require(['tabview','treeview'],function(a,b){
    var tab = new a.tabview();
    var tree = new b.treeview();
    alert(tab.name);
    alert(tab.animate);
    alert(tab.dec);
    alert(tree.name);
});

使用该方法加载tabview、treeview两个模块,而tabview会去依赖animate模块,由于模块返回的都是对象,那我们可以new一个对象去调用加载模块中的方法和属性!

在main.js,我们需要去配置一下模块的路径,就那上面例子来说,需要配置一下几个模块的路径,如下:

require.config({
   paths: {
     "tabview": "js/tabview",
     "animate": "js/animate",
     "treeview": "js/treeview"
   }
 });

//另一种则是直接改变基目录(baseUrl)。后缀.js可以省略
require.config({
    baseUrl: "js/lib",
    paths: {
      "jquery": "jquery.min",
      "underscore": "underscore.min",
      "backbone": "backbone.min"
    }
});

这样require.js便可以很灵活地使用来进行模块化管理了,这里有一个基于require.js去搭建一个web组件(弹窗的demo),很值得学习一下!可以去看看!github地址:https://github.com/xiaobinwu/require.js-Popup-window-

require最常用的方法

require('http') 内置模块

require('./server')  “./”表示当前路径,后面跟的是相对路径

require("../lib/server") ../表示上一级目录,后面跟的也是相对路径

server.js

    var http = require('http');
    function start(){
        server = http.createServer(function (req, res) {   
              res.writeHeader(200, {"Content-Type": "text/plain"});   
              res.end("Hello oschina\n");   
        })   
        server.listen(8000);   
        console.log("httpd start @8000");   
    }
    exports.start = start;   

index.js

    //路径根据自己的实际情况而定  
    var server = require("./learnNode/server");
    server.start();

下面介绍require

模块

Node 使用 CommonJS 模块系统。

Node 有一个简单的模块加载系统。在 Node 中,文件和模块一一对应。比如,在 foo.js 加载同一目录中的 circle.js 模块。

foo.js 的内容:

var circle = require('./circle.js');
console.log( 'The area of a circle of radius 4 is '
           + circle.area(4));

circle.js 的内容:

var PI = Math.PI;

exports.area = function (r) {
  return PI * r * r;
};

exports.circumference = function (r) {
  return 2 * PI * r;
};

模块 circle.js 导出了 area() 函数和 circumference() 函数,这样它们就能从模块外部访问了。要导出对象,将其添加到特殊的 exports 对象就行。

模块的局部变量是私有的。在本例中,变量 PI 是 circle.js 私有的。

核心模块

Node 有一些已编译成二进制的模块,这些模块将在本文档的其他地方详细介绍。

核心模块在 Node 源代码的 lib/ 文件夹中定义。

使用 require() 时,核心模块总是优先加载。例如,require('http') 总是返回内置的 HTTP 模块,即使该名称的文件存在。

文件模块

如果没有找到确切的文件,Node 将尝试给所需的文件名添加 .js 后缀再加载,然后再尝试 .node。

.js 文件被视为 JavaScript 文本文件,而 .node 文件被视为已编译的插件模块,用 dlopen 加载。

模块以 '/' 开头表示使用文件的绝对路径。例如,require('/home/marco/foo.js') 将加载 /home/marco/foo.js 文件。

模块以 './' 开头表示调用 require() 时使用相对路径。也就是说,为了保证 require('./circle') 能找到,circle.js 必须和 foo.js 在同一目录。

如果不以 '/' 或'./' 开头,该模块可以是一个“核心模块”,也可是一个从 node_modules 文件夹中加载的模块。
从 `node_modules` 文件夹中加载

如果传递给 require() 有模块标识符是不是原生模块,而且不以 '/'、'../' 或'./' 开头,那么 Node 从当前模块的父目录+/node_modules 这个位置尝试加载。

如果还是没有找到,那么它跳到上层目录并依此类推,直到找到模块,或者达到根目录为止。

例如,如果在文件 '/home/ry/projects/foo.js' 中调用 require('bar.js'),那么 Node 将在下列位置查找,顺序如下:

    /home/ry/projects/node_modules/bar.js
    /home/ry/node_modules/bar.js
    /home/node_modules/bar.js
    /node_modules/bar.js

这就允许程序将依赖关系本地化,防止它们冲突。

优化 `node_modules` 查找过程

当嵌套依赖关系的层次很深时,这个文件查找列表可能会变得很长。因此,在查找时进行如下优化:

首先,/node_modules 不会附加到一个以 /node_modules 结尾的文件夹后面。

其次,如果调用 require() 的文件已经在一个 node_modules 层级里,那么最顶层的 node_modules 文件夹将被视为搜索树的根。

例如,如果在文件 '/home/ry/projects/foo/node_modules/bar/node_modules/baz/quux.js' 中调用 require('asdf.js'),那么 Node 将搜索下列位置:

    /home/ry/projects/foo/node_modules/bar/node_modules/baz/node_modules/asdf.js
    /home/ry/projects/foo/node_modules/bar/node_modules/asdf.js
    /home/ry/projects/foo/node_modules/asdf.js

以文件夹作为模块

Node 允许用户在独立的目录中方便地组织程序,然后提供单一入口指向该库。有三种方式可以将文件夹作为 require() 的参数。

第一种方式是在该文件夹中创建 package.json 文件,指定一个 main 模块。一个典型的 package.json 文件可能看起来像这样:

{ "name" : "some-library",
  "main" : "./lib/some-library.js" }

如果此文件位于 ./some-library 文件夹,则 require('./some-library') 会尝试加载 ./some-library/lib/some-library.js。

这是 Node 能找到 package.json 文件的情况。

如果在该目录中没有 package.json 文件,那么 Node 将尝试加载该目录中的 index.js 或 index.node 文件。例如,如果上面的例子找不到 package.json,那么 require('./some-library') 将试图加载:

    ./some-library/index.js
    ./some-library/index.node

缓存

模块在首次被加载后会缓存起来。这意味着每次调用 require('foo') 将得到完全相同的对象,如果它被解析为同一个文件的话。

总结

为了得到调用 require() 时被载入的确切的文件名,使用 require.resolve() 函数。

综上所述,这是 require.resolve 的伪码描述:

require(X)
1. If X is a core module,
   a. return the core module
   b. STOP
2. If X begins with `./` or `/`,
   a. LOAD_AS_FILE(Y + X)
   b. LOAD_AS_DIRECTORY(Y + X)
3. LOAD_NODE_MODULES(X, dirname(Y))
4. THROW "not found"

LOAD_AS_FILE(X)
1. If X is a file, load X as JavaScript text.  STOP
2. If X.js is a file, load X.js as JavaScript text.  STOP
3. If X.node is a file, load X.node as binary addon.  STOP

LOAD_AS_DIRECTORY(X)
1. If X/package.json is a file,
   a. Parse X/package.json, and look for "main" field.
   b. let M = X + (json main field)
   c. LOAD_AS_FILE(M)
2. LOAD_AS_FILE(X/index)

LOAD_NODE_MODULES(X, START)
1. let DIRS=NODE_MODULES_PATHS(START)
2. for each DIR in DIRS:
   a. LOAD_AS_FILE(DIR/X)
   b. LOAD_AS_DIRECTORY(DIR/X)

NODE_MODULES_PATHS(START)
1. let PARTS = path split(START)
2. let ROOT = index of first instance of "node_modules" in PARTS, or 0
3. let I = count of PARTS - 1
4. let DIRS = []
5. while I > ROOT,
   a. if PARTS[I] = "node_modules" CONTINUE
   c. DIR = path join(PARTS[0 .. I] + "node_modules")
   b. DIRS = DIRS + DIR
6. return DIRS

从 `require.paths` 加载

在 Node 中,require.paths 是一个字符串数组,表示模块不以 '/' './' 或 '..' 打头的搜索路径。例如,如果 require.paths 设置为:

[ '/home/micheil/.node_modules',
  '/usr/local/lib/node_modules' ]

则调用 require('bar/baz.js') 会搜索以下位置:

    1: '/home/micheil/.node_modules/bar/baz.js'
    2: '/usr/local/lib/node_modules/bar/baz.js'

可以在运行时修改 require.paths 数组来改变这种行为。

它的值最初从 NODE_PATH 环境变量而来,那是一个冒号分隔的绝对路径列表。在前面的例子中,NODE_PATH 环境变量可能被设置为:

/home/micheil/.node_modules:/usr/local/lib/node_modules

只有使用上面的 node_modules 算法找不到模块时才会尝试 require.paths。全局模块的优先级低于捆绑依赖。

**注意** 请不要修改 `require.paths`

出于兼容性的考虑,require.paths 仍然是模块查找过程的首选策略。尽管如此,它可能会在将来的版本中废弃。

虽然它看起来似乎是个好主意,但在实践中一个可变的 require.paths 列表往往是麻烦和混乱的根源。

修改 `require.paths` 毫无用处

这行代码并不会像期望的那样:

require.paths = [ '/usr/lib/node' ];

它的结果就是丢弃了 Node 实际的模块查找路径引用,并创建了一个毫无用处的指向别处的新的引用。
在 `require.paths` 中加入相对路径……不是个好主意

如果你这样做:

require.paths.push('./lib');

它不会添加 ./lib 在文件系统上已解析的完整路径。相反,它实际增加的是 './lib',这意味着如果你在 /a/b/x.js 中 require('y.js'),那么它会查找 /a/b/lib/y.js。如果你之后又在 /l/m/n/o/p.js 中 require('y.js'),那么它就会查找 /l/m/n/o/lib/y.js。

在实践中,人们往往将它作为捆绑依赖的临时解决办法,这个技巧是不太稳妥的。
零隔离

有一种糟糕的设计:所有模块共用一个 require.paths 数组。

结果,如果一个 Node 程序依赖于这种行为,它可能会永久而微妙地改变同一进程中其它 Node 程序的行为。当应用程序的复杂度增加时,我们倾向于封装功能,这些行为很难预料的部分会成为开发者的恶梦。

时间: 2024-10-29 14:18:38

js框架require.js使用入门教程的相关文章

国人开发的比较优秀的js框架:como js

今天 @karryZhang同学提到一个新的国产的js框架como js,我就去看了一下,觉得还不错.另外我们一直在学习和使用老外写的东西,也应该放眼国内,发现并推广一些国人开发的比较优秀的项目. como js是一个比较轻的js框架,但是功能还是比较强大的,实用性比较强.它有以下特性: 对原生对象如String扩展常用函数 简约而快速的CSS选择器 支持类的声明与继承 强大的js包扩展机制,支持CSS按需加载 非侵入式切换调用,与第三方框架并存 高效.易操作的动画执行 支持主流浏览器 当然,可

js函数的使用一[入门教程]

1 ,函数: function是一个定义一次 却可以多次调用的js代码. 当一个函数被一个对象调用时,那么这个函数就叫做这个对象的方法. function cssrain( x , y) {  //code } 解释: cssrain  :  为函数名: ( )     :   为 运算符: x ,  y  :   为 参数: 2 ,函数的返回值: function a(x){     document.write(x); } function b(y){    document.write(y

js函数的使用二[入门教程]

6,实战: 编写一个javascript图片馆: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head>   <meta http-equiv="conte

PHP MVC框架之错误捕捉入门教程

前三篇文章已经把MVC的结构原理都简单的进行了说明和演示...当然,不是说一个框架就只有那点东西,一个良好的框架所要求的功能还是要很全面的,例如友好的错误输出,安全处理,防止跨域攻击等 好了,我们一步一步来.这节要说的是错误捕捉,其实这个不难,只要理解2个方法就可以做好错误捕捉的程序.  代码如下 复制代码 register_shutdown_function('functionname');   set_error_handler('functionname');  第一个方法,是注册一个sh

Require.JS快速入门

Require.JS 介绍 Require.JS 是一个基于 AMD 规范的 JavaScript 模块加载框架.实现 JavaScript 文件的异步加载,管理模块之间的依赖性,提升网页的加载速度. AMD 是 Asynchronous Module Definition 的缩写,意思就是 异步模块定义.它采用异步方式加载模块,模块的加载不影响它后面语句的运行.所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行. 官网地址: Require.JS 的诞生主要

Javascript模块化编程(三):require.js的用法

今天介绍如何将它们用于实战. 我采用的是一个非常流行的库require.js. 一.为什么要用require.js? 最早的时候,所有Javascript代码都写在一个文件里面,只要加载这一个文件就够了.后来,代码越来越多,一个文件不够了,必须分成多个文件,依次加载.下面的网页代码,相信很多人都见过. <script src="1.js"></script> <script src="2.js"></script> &

javascript 模块化编程 require.js

一.为什么要用require.js? 最早的时候,所有Javascript代码都写在一个文件里面,只要加载这一个文件就够了.后来,代码越来越多,一个文件不够了,必须分成多个文件,依次加载.下面的网页代码,相信很多人都见过. <script src="1.js"></script> <script src="2.js"></script> <script src="3.js"></s

第二次聊一聊JS require.js模块化工具的基础知识_javascript技巧

前一篇:JS模块化工具我们以非常简单的方式引入了requirejs:http://www.jb51.net/article/82527.htm,这一篇将讲述一下requirejs中的一些基本知识,包括API使用方式等 基本API require会定义三个变量:define,require,requirejs,其中require === requirejs,一般使用require更简短 define 从名字就可以看出这个api是用来定义一个模块require 加载依赖模块,并执行加载完后的回调函数

require.js的用法详解_javascript技巧

一.为什么要用require.js? 最早的时候,所有Javascript代码都写在一个文件里面,只要加载这一个文件就够了.后来,代码越来越多,一个文件不够了,必须分成多个文件,依次加载.下面的网页代码,相信很多人都见过. <script src="1.js"></script> <script src="2.js"></script> <script src="3.js"></s