NodeJs快速开发应用(四)-模块与npm包管理工具

188 阅读7分钟

在Node.js中,以模块为单位划分所有功能,并且提供了一个完整的模块加载机制,这使得我们可以将应用程序划分为各个不同的部分,并且对这些部分进行很好地协同管理。通过将各种可重用代码编写在各种模块中的方法,我们可以大大减少应用程序的代码量,提高应用程序的开发效率以及应用程序代码的可读性。通过模块加载机制,我们也可以将各种第三方模块引入到我们的应用程序中。本章将对Node.js中的模块及模块加载机制进行详细介绍。另外,在Node.js中,提供了一个npm包管理工具,用于从第三方网站上下载各种Node.js包。

从模块外部访问模块内的成员

使用 exports 对象

在一个模块文件中定义的本地(即非函数内定义的)变量、函数或对象只在该模块内有效,当你需要从模块外部引用这些变量、函数或对象时,需要在该模块文件内使用 exports 对象,方法如下所示。

var myMsg=”hello”;
var funcname=function() {
   return 'I'm funcname1 function.';
};
exports.msg=myMsg;
exports.funcname=funcname;

然后,即可从模块外部访问这些变量、函数或对象。

例如,将上述代码保存为 foo.js 文件后,即可使用如下所示的代码访问模块内的 msg 变量及 funcname 函数。

//加载当前目录下的 foo.js 模块文件并将其赋值给 foo 模块对象
var foo = require('./foo.js');
console.log(foo.msg);//通过 foo模块对象的 msg属性访问 foo.js模块内的 myMsg变量
//通过 foo模块对象的 funcname属性访问 foo.js模块内的 funcname函数
console.log(foo.funcname ());

将模块定义为类

你也可以在模块文件内将 exports 对象书写为“module.exports”,但是在需要将模块定义为一个类时,只能使用“module.exports”的书写方法。 在该脚本文件中,我们将定义一个 foo 类,为该类创建如表 4-1 所示的变量及函数:

/**
​
 * 将模块定义为类
 * 你也可以在模块文件内将exports对象书写为“module.exports”,但是在需要将模块定义为一个类时,只能使用“module.exports”的书写方法。
   */
var _name, _age;//私有变量
var name = '', age = 0;//公有变量//模块对象的构造函数
var foo = function (name, age) {
    _name = name;
    _age = age;
}
​
//获取私有变量_name变量值
foo.prototype.GetName = function () {
    return _name
}
//设置私有变量_name变量值
foo.prototype.SetName = function (name) {
    _name = name
}
​
foo.prototype.GetAge = function () {
    return _age
}
foo.prototype.SetAge = function (age) {
    _age = age
}
foo.prototype._name = name;
foo.prototype._age = age;
module.exports = foo;
​
var foo=require('./foo.js');
var myFoo = new foo("Tom",40); //
//获取修改前的私有变量值
console.log("获取修改前的私有变量值", myFoo.GetAge(), myFoo.GetName())
//修改私有变量值
myFoo.SetName("Bob")
myFoo.SetAge(10)
//获取修改后的私有变量值
console.log("获取修改后的私有变量值", myFoo.GetAge(), myFoo.GetName())
//获取修改前的公有变量值
console.log('获取修改前的公有变量值', myFoo.name, myFoo.age)
//修改公有变量值
myFoo.name = '嚣张'; myFoo.age = 100;
//获取修改后的公有变量值
console.log('获取修改后的公有变量值', myFoo.name, myFoo.age);

打印结果为:

image.png

组织与管理模块

从 node_modules 目录中加载模块

如果在 require 函数中只使用如下所示的方法指定文件名,但不指定路径,require('bar.js') 则 Node.js 将该文件视为 node_modules 目录下的一个文件。例如,在一个完整路径为“/home/ry/projects/app.js”(在 UNIX 操作系统中,“/”表示根目录,在 Windows 操作系统中,“/”表示磁盘根目录,该路径表示根目录或磁盘根目录下的 ry 子目录下的 projects 子目录下的 app.js 文件)的 app.js 文件中使用上述代码,则 Node.js 为“bar.js”模块使用的加载路径依次为:

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

/home/ry/node_modules/bar.js

/home/node_modules/bar.js

/node_modules/bar.js

使用这种方式加载模块比指定路径加载模块的方式更为灵活,因为你可以移动模块文件的所在位置而不需修改代码中指定的路径。

module 模块对象的属性

image.png ·module.id:属性值为当前模块的 ID。在默认情况下,主模块的 ID 属性值为“.”,其他模块的 ID 属性值为该模块文件的绝对路径。在模块文件中可以修改当前模块的 ID 属性值。 ·module.filename:属性值为当前模块文件的文件名。 ·module.loaded:属性值为布尔值,当属性值为 false 时表示模块尚未加载完毕,属性值为 true 时表示模块加载完毕。 ·module.parent:属性值为当前模块的父模块对象,即调用当前模块的模块对象。 ·module.children:属性值为一个数组,其中存放了当前模块的所有子模块对象,即当前模块中已加载的所有模块对象。

image.png

包与npm包管理工具

node中的包

Node.js中的包 在Node.js中,可以通过包来对一组具有相互依赖关系的模块进行统一管理。通过包的使用,我们可以将某个独立的功能封装起来。 在Node.js中,一个包事实上是一个目录,其中包含了用于对包进行描述的JSON格式的package.json文件。在一个包中,通常包含如下所示的一些内容: 1)在包的根目录中存放package.json文件。
2)在bin子目录中存放二进制文件。
3)在lib子目录中存放JavaScript文件。
4)在doc子目录存放对包或包的使用方法进行说明的文档文件。
5)在test子目录中存放一些对包进行单元测试用的文件。 在一个package.json文件中,一个package.json文件中通常应该包含的字段及其作用如下所示:

  • name,包名。包名是唯一的,由小写字母、数字和下划线组成,不能含空格。
  • preferglobal,是否支持全局安装。字段值为true时支持全局安装,字段值为false时不支持全局安装。
  • description,包说明。对包进行简要描述。
  • version,版本号。
  • author,作者信息数组。每个数组元素中可包含name(作者姓名)字段、email(作者E-mail)字段、web(作者网址)字段。
  • maintainers,包维护者信息数组。每个数组元素中可包含name(包维护者姓名)字段、email(包维护者E-mail)字段、web(包维护者网址)字段。
  • bugs,bug的提交地址,可以是网址或电邮地址。
  • licenses,许可证数组。每个元素要包含type(许可证名称)和url(链接到许可证文本的地址)字段。
  • repository,仓库托管地址数组。每个元素要包含type(仓库的类型,如Git)、url(仓库地址)和path(相对于仓库的路径,可选)字段。
  • keywords,关键字数组,通常用于搜索。 11)dependencies,本包所依赖的包。是一个关联数组,由包名和版本号组成。 一个典型的package.json文件中的内容类似如下所示。
{
    "name": "forever",
    "preferGlobal": "true",
    "description": "A simple CLI tool for ensuring that a given node script 
    runs continuously (i.e. forever)",
    "version": "0.10.8",
    "author": {
        "name": "Nodejitsu Inc.",
        "email": "info@nodejitsu.com"
    },
    "maintainers": [
        {
            "name": "indexzero",
            "email": "charlie@nodejitsu.com"
        },
        {
            "name": "mmalecki",
            "email": "maciej@nodejitsu.com"
        },
        {
            "name": "avianflu",
            "email": "charlie@charlieistheman.com"
        }
    ],
    "repository": {
        "type": "git",
        "url": "http:// github.com/nodejitsu/forever.git"
    },
    "keywords": [
        "cli",
        "fault tolerant",
        "sysadmin",
        "tools"
    ],
    "dependencies": {
        "colors": "0.6.0-1",
        "cliff": "0.1.8",
        "flatiron": "0.3.5",
        "forever-monitor": "1.2.2",
        "nconf": "0.6.7",
        "nssocket": "~0.5.1",
        "optimist": "0.4.0",
        "pkginfo": "0.3.0",
        "timespan": "2.0.1",
        "watch": "0.7.0",
        "utile": "0.1.7",
        "winston": "0.7.1"
    }
}

npm包管理工具

当我们需要下载forever包时,可以在命令行提示窗口中输入以下命令:npm install forever 该命令将把forever包安装在命令行提示窗口当前目录下的node_modules子文件夹中。
在该命令中加入“-g”选项,则将把forever包安装在Node.js的全局包的安装路径中(所有应用程序均可使用该路径下的包),命令如下所示:npm install –g forever
我们可以通过以下命令来查看Node.js的全局包的安装路径:npm root -g
通过以下命令来修改Node.js的全局包的安装路径:npmconfig set prefix“d:\node”
该命令将把Node.js的全局包的安装路径修改为“d:\node\node_modules”。
我们可以通过如下所示的命令来查看命令行提示窗口当前目录下所安装的所有包:npmlist

通过如下所示的命令来查看Node.js的全局包的安装路径下安装的所有包:npmlist -g
通过如下所示的命令来卸载命令行提示窗口当前目录下安装的某个包:npm uninstall <包名>
通过如下所示的命令来卸载Node.js的全局包的安装路径下安装的某个包:npm uninstall –g <包名>
通过如下所示的命令来更新命令行提示窗口当前目录下安装的某个包:npm update <包名>
通过如下所示的命令来更新Node.js的全局包的安装路径下安装的某个包:npm update –g <包名>
通过如下所示的命令来更新命令行提示窗口当前目录下安装的所有包:npm update
通过如下所示的命令来更新Node.js的全局包的安装路径下安装的所有包:npm update–g