模块
- 在Node.js中,以模块为单位划分所有功能,并且提供了一个完整的模块加载机制,这时的我们可以将应用程序划分为各个不同的部分。
- 除了node提供的模块,我们也可以自己自定义一些模块。
- 模块:简单来说:每一个javascript文件都是一个模块,提供一些功能的实现。而多个js文件相互require,实现一个较为负复杂的功能,他们整体对外部提供一套功能,他们整体也正为模块。
- Node.js中,一个javascript文件中定义的变量、函数、都只在这个文件中有效。当需要在这个js文件的外部使用这些变量、函数时。必须使用exports对象进行暴露,使用者要用require()来引入这个js文件。
模块分类
简单划分,可以将Node.js中的模块分成两大类:
系统模块(核心模块)
用户模块
其中,系统模块是Node.js自带的模块,比如http、fs、net、url、path等,可以直接使用。核心模块,Node.js中是内置好的。
用户模块不是Node.js本身的,又可以分为两种:
第三方模块,一些比较通用的,但是Node.js自身没有提供的,这一类数量很庞大
自定义模块,通常是在当前项目中,需要根据需求自己编写的js代码
加载模块
如何在Node.js中加载模块呢?
根据模块类型的不同,加载的方式略有不同。相同的是,都会使用 require 函数。格式:require(模块路径);
模块路径的写法,根据模块类型的不同,写法也不同:
核心模块和第三方模块的写法一样,只需要写上模块名即可。
自定义模块,需要使用相对路径来引入,必须使用 ./ 或者 ../ 开头。
(1)核心模块的载入
核心模块是Node.js自带的,本身就具备的,直接载入就可以使用。
(2)第三方模块的载入
首先,需要保证有一个第三方模块,需要先安装第三方模块,使用npm 命令安装即可。
npm install 模块名。
本地安装的时候,需要先进入对应的目录,使用命令来安装。
虽然,加载模块的写法和核心模块一样,但是原理不太一样。如果是第三方模块,它最加载的时候,一定会在当前目录下,寻找 node_modules文件夹,在里面找对应的这模块,如果找到,就直接使用。如果没有找到,则会到父级目录中找node_modules文件夹,找是否有该模块,重复这个过程,直到根目录。如果到根目录,也没有找到,就会报错。
(3)加载自定义模块
先创建一个模块,其实就是一个js文件:mymodule.js
然后,使用require引入,const myModule = require('./mymodule.js');
如果没有使用相对路径,会报错。
还有几个细节需要注意一下:
模块就是文件,一般就是js文件,js文件是有后缀的,后缀是可以省略的,核心模块和第三方模块必须省略,自定义模块比较随意,两种都行。
如果没有写后缀,require 方法在加载的时候,当文件不带后缀,Node.js会依照 目录 ->.js-> .json-> .node 的顺序进行查找,如果所有模块路径都找不到该文件,则抛出异常。
自定义模块的实现
默认情况下,任何一个模块,被载入时,得到的是一个空对象,就是 module.exports;我们可以直接在js文件中使用module.exports。
在Node.js中,还有一个对象exports,它实际上是module.exports的一个引用,相当于exports = module.exports。
如果使用的是module.exports,那么直接赋值即可,如果使用的是exports,不能直接赋值,原因很简单嘛,又涉及到了对象数值的传递了。所以小结一下:
任何一个模块(js文件)被 require 时,返回的是 module.exports 对象,默认为空。Node.js为了方便,提供了一个exports对象,指向module.exports,相当于执行了exports=module.exports。如果需要提供对外接口,需要给module.exports赋值为一个新的对象,或者使用exports.属性名=值的形式。
为了保险起见,我们可以写成:exports = module.exports = {}。
HTTP模块
Node.js中,将很多的功能,划分为了一个个mudule,大陆的书翻译为模块;台湾的书,翻译为模组。
这是因为,有一些程序需要使用fs功能(文件读取功能),有一些不用的,所以为了效率,你用啥,你就require啥。
|
设置一个响应头:
|
我们现在来看一下req里面能够使用的东西。
最关键的就是req.url属性,表示用户的请求URL地址。所有的路由设计,都是通过req.url来实现的。
我们比较关心的不是拿到URL,而是识别这个URL。
sayhello.js文件 中的代码
|
msg与say(),都是在这个js文件中才有效。要想再其他的文件中使用,这两个属性。必须在当先文件中使用exports将这些属性和方法进行暴露,然后在使用者中必须先引入这个模块。
server.js中的代码
|
这里require()获得的是exports对象,其中有sayhello.js中的所有属性和方法 声明变量say接受exports对象。
- Js文件中,可以使用exports暴露很多东西:属性、方法
|
使用者中,只需要require()一次,就能获得所有的属性和方法。声明一个变量来接受暴露的数据,这个变量就相当于是模块中的exports对象,使用这个变量就可以调用所有的数据。
Node中,js文件与js文件,就是使用这种方式(exports+require()),构成网状。
如果这个模块中中要暴露的是一个构造函数,就不能使用上边的方式进行暴露。使用的方式为:
|
并且这时是直接将People构造函数,暴露出去。
使用这使用这个构造函数
|
这是一个特殊要求,当模块中要暴露的是一个构造函数时,要这么做。我们可以看出,这个模块也只能暴露构造函数。
|
总的来说,node中js与js文件之间的合作模式有两种:暴露属性和方法 暴露构造函数
|
node_modules文件夹:是专门用来存储模块的文件夹。如果require()中的路径没有写成正常的路径方式,就会去这个文件中查找模块。
特殊的模块:包
- 将咱们的文件模块,放在一个文件夹中,咱们可以通过require()这个文件件,间接的require()里边的文件。
- 包中的文件模块必须是index.js
- 同时存在包和模块重名能够,使用的是模块。
- 这个index.js叫做包的入口文件,入口文件默认的名称是index.js。但是我们可以通过更改包的配置,改变入口文件的名称。
NPM
- 包管理器
- 初始化包————设置包的配置文件,更改包的属性
- 下载或者是更新第三方包
- NPM
<1>服务器
<2>网站npmjs
<3>npm 程序,
|
|
百度:npm全局安装目录
fs模块中使用的路径——特殊的相对路径
- 相对路径:本来相对路径指的就是相对于当前文件的路径
- 而在fs模块中使用的相对路径,它非常特殊。也是相对路径,但是他相对的是咱们命令台所指的路径。
- 若果想在fs模块中实现路径相对当前文件,要是用一个特殊写法
- var fs = require('fs');
- fs.readFile('./test.txt', function(err,data) {
- if(err){
- console.log('err');
- }else{
- console.log('success');
- }
- })
这里的'./test.txt',不是相对于当前文件,而是相对于的命令台中的路径。
要想在fs模块时表示相对当前文件,需要下列的写法
文件中有一个a.js test文件夹 test文件夹中有一个b.js c.js c.txt a引用b var b = require(‘./test/b.js’); B要引用c var c = require(‘./c.js’); C中console.log(‘我是c’);
此时执行a.js |
补充:require()时,会自动执行被require()的模块。 |
以上没有任何问题,在做其他操作时,所有的相对路径都是相对于代码所在的文件。
而如果此时我们要在b.js中读取一个同目录的c.txt,就会出问题。
原因是,当程序执行时,所有的fs使用的相对路径,都是相对于控制台所指的路径。那么就找不到要读取的文件。
所以在c.js中读取这个文件使用绝对路径。
__dirname: 总是返回被执行的 js 所在文件夹的绝对路径
__filename: 总是返回被执行的 js 的绝对路径
|
./ 当前路径
../ 上一级路径