Node模块与包及NPM详解

模块

  1. 在Node.js中,以模块为单位划分所有功能,并且提供了一个完整的模块加载机制,这时的我们可以将应用程序划分为各个不同的部分。
  2. 除了node提供的模块,我们也可以自己自定义一些模块。
  3. 模块:简单来说:每一个javascript文件都是一个模块,提供一些功能的实现。而多个js文件相互require,实现一个较为负复杂的功能,他们整体对外部提供一套功能,他们整体也正为模块。
  4. 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啥。

 

  1. //这个案例简单讲解http模块
  2. //引用模块
  3. var http = require("http");
  4.  
  5. //创建一个服务器,回调函数表示接收到请求之后做的事情
  6. var server = http.createServer(function(req,res){
  7. //req参数表示请求,res表示响应
  8. console.log("服务器接收到了请求" + req.url);
  9. res.end();
  10. });
  11. //监听端口
  12. server.listen(3000,"127.0.0.1");

 

设置一个响应头:

  1. res.writeHead(200,{"Content-Type":"text/plain;charset=UTF8"});

 


我们现在来看一下req里面能够使用的东西。

最关键的就是req.url属性,表示用户的请求URL地址。所有的路由设计,都是通过req.url来实现的。

我们比较关心的不是拿到URL,而是识别这个URL。

sayhello.js文件 中的代码

  1. var say = function(){
  2. console.log('hello world');
  3. }
  4. var msg = 'hello world';
  5.  
  6. exports.msg = msg;
  7. exports.say = say;

msg与say(),都是在这个js文件中才有效。要想再其他的文件中使用,这两个属性。必须在当先文件中使用exports将这些属性和方法进行暴露,然后在使用者中必须先引入这个模块。

server.js中的代码

  1. var sayhello = require('./sayhello');
  2.  
  3. console.log(sayhello.msg);

这里require()获得的是exports对象,其中有sayhello.js中的所有属性和方法 声明变量say接受exports对象。

  1. Js文件中,可以使用exports暴露很多东西:属性、方法
  1. var say = function(){
  2. console.log('hello world');
  3. }
  4. var msg = 'hello world';
  5.  
  6. exports.msg = msg;
  7. exports.say = say;

使用者中,只需要require()一次,就能获得所有的属性和方法。声明一个变量来接受暴露的数据,这个变量就相当于是模块中的exports对象,使用这个变量就可以调用所有的数据。

Node中,js文件与js文件,就是使用这种方式(exports+require()),构成网状。

如果这个模块中中要暴露的是一个构造函数,就不能使用上边的方式进行暴露。使用的方式为:

  1. function People(name,age){
  2. this.name = name;
  3. this.age = age;
  4. this.say = function(){
  5. console.log(this.name+this.age);
  6. }
  7. }
  8. module.exports = People;

 

并且这时是直接将People构造函数,暴露出去。

使用这使用这个构造函数

  1. var People = require('./sayhello');
  2. var p1 = new People('孙晨',18);
  3. p1.say();

这是一个特殊要求,当模块中要暴露的是一个构造函数时,要这么做。我们可以看出,这个模块也只能暴露构造函数。

  1.  

总的来说,node中js与js文件之间的合作模式有两种:暴露属性和方法 暴露构造函数

  1.  

node_modules文件夹:是专门用来存储模块的文件夹。如果require()中的路径没有写成正常的路径方式,就会去这个文件中查找模块。

特殊的模块:包

  1. 将咱们的文件模块,放在一个文件夹中,咱们可以通过require()这个文件件,间接的require()里边的文件。
    1. 包中的文件模块必须是index.js
    2. 同时存在包和模块重名能够,使用的是模块。
    3. 这个index.js叫做包的入口文件,入口文件默认的名称是index.js。但是我们可以通过更改包的配置,改变入口文件的名称。

 

NPM

  1. 包管理器
    1. 初始化包————设置包的配置文件,更改包的属性
    2. 下载或者是更新第三方包
    3. NPM

  <1>服务器

  <2>网站npmjs

  <3>npm 程序,

  1. npm -v
  2. npm init 初始化包
  3.  
  4. npm install包名    在当前文件下载
  5. npm install包名 -g   在全局文件下载
  6.  
  7.  
  1.  

百度:npm全局安装目录

 

fs模块中使用的路径——特殊的相对路径

  1. 相对路径:本来相对路径指的就是相对于当前文件的路径
  2. 而在fs模块中使用的相对路径,它非常特殊。也是相对路径,但是他相对的是咱们命令台所指的路径。
  3. 若果想在fs模块中实现路径相对当前文件,要是用一个特殊写法
  1. var fs = require('fs');
  2. fs.readFile('./test.txt', function(err,data) {
  3. if(err){
  4. console.log('err');
  5. }else{
  6. console.log('success');
  7. }
  8. })

这里的'./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 的绝对路径

  1. var fs = require('fs');
  2. fs.readFile(__dirname+'/c.txt', function(err,data) {
  3. if(err){
  4. console.log('err');
  5. }else{
  6. console.log('success');
  7. }
  8. })

 

./  当前路径

../ 上一级路径

猜你喜欢

转载自blog.csdn.net/qq_43198747/article/details/86605291