一、Node js入门
1.如果要运行一大段代码的话,可以先写一个JS文件再运行。例如有以下`hello.js`。
function hello() {
console.log('Hello World!');
}
hello();
写好后在终端下键入`node hello.js`运行,结果如下:
$ node hello.js
Hello World!
2.#### require
`require`函数用于在当前模块中加载和使用别的模块,传入一个模块名,返回一个模块导出对象。模块名可使用相对路径(以`./`开头),或者是绝对路径(以`/`或`C:`之类的盘符开头)。另外,模块名中的`.js`扩展名可以省略。以下是一个例子。
var foo1 = require('./foo');
var foo2 = require('./foo.js');
var foo3 = require('/home/user/foo');
var foo4 = require('/home/user/foo.js');
// foo1至foo4中保存的是同一个模块的导出对象。
另外,可以使用以下方式加载和使用一个JSON文件。
var data = require('./data.json');
3.#### exports
`exports`对象是当前模块的导出对象,用于导出模块公有方法和属性。别的模块通过`require`函数使用当前模块时得到的就是当前模块的`exports`对象。以下例子中导出了一个公有方法。
exports.hello = function () {
console.log('Hello World!');
};
4.#### module
通过`module`对象可以访问到当前模块的一些相关信息,但最多的用途是替换当前模块的导出对象。例如模块导出对象默认是一个普通对象,如果想改成一个函数的话,可以使用以下方式。
module.exports = function () {
console.log('Hello World!');
};
以上代码中,模块默认导出对象被替换为一个函数。
5.#### 完整示例
例如有以下目录。
- /home/user/hello/
- util/
counter.js
main.js
其中`counter.js`内容如下:
var i = 0;
function count() {
return ++i;
}
exports.count = count;
该模块内部定义了一个私有变量`i`,并在`exports`对象导出了一个公有方法`count`。
主模块`main.js`内容如下:
var counter1 = require('./util/counter');
var counter2 = require('./util/counter');
console.log(counter1.count());
console.log(counter2.count());
console.log(counter2.count());
运行该程序的结果如下:
$ node main.js
1
2
3
可以看到,`counter.js`并没有因为被require了两次而初始化两次。
第二章、代码组织
1.`require`函数路径解析
`require`函数支持斜杠(`/`)或盘符(`C:`)开头的绝对路径,也支持`./`开头的相对路径。但这两种路径在模块之间建立了强耦合关系,一旦某个模块文件的存放位置需要变更,使用该模块的其它模块的代码也需要跟着调整,变得牵一发动全身。因此,`require`函数支持第三种形式的路径,写法类似于`foo/bar`,并依次按照以下规则解析路径,直到找到模块位置。
(1)内置模块
如果传递给`require`函数的是NodeJS内置模块名称,不做路径解析,直接返回内部模块的导出对象,例如`require('fs')`。
(2)node_modules目录
NodeJS定义了一个特殊的`node_modules`目录用于存放模块。例如某个模块的绝对路径是`/home/user/hello.js`,在该模块中使用`require('foo/bar')`方式加载模块时,则NodeJS依次尝试使用以下路径。
/home/user/node_modules/foo/bar
/home/node_modules/foo/bar
/node_modules/foo/bar
(3) NODE_PATH环境变量
与PATH环境变量类似,NodeJS允许通过NODE_PATH环境变量来指定额外的模块搜索路径。NODE_PATH环境变量中包含一到多个目录路径,路径之间在Linux下使用`:`分隔,在Windows下使用`;`分隔。例如定义了以下NODE_PATH环境变量:
NODE_PATH=/home/user/lib:/home/lib
当使用`require('foo/bar')`的方式加载模块时,则NodeJS依次尝试以下路径。
/home/user/lib/foo/bar
/home/lib/foo/bar
2.包管理——便于管理和使用,由多个子模块组成
在组成一个包的所有子模块中,需要有一个入口模块,入口模块的导出对象被作为包的导出对象。例如有以下目录结构。
- /home/user/lib/
- cat/
head.js
body.js
main.js
其中`cat`目录定义了一个包,其中包含了3个子模块。`main.js`作为入口模块,其内容如下:
var head = require('./head');
var body = require('./body');
exports.create = function (name) {
return {
name: name,
head: head.create(),
body: body.create()
};
};
在其它模块里使用包的时候,需要加载包的入口模块。接着上例,使用`require('/home/user/lib/cat/main')`能达到目的,但是入口模块名称出现在路径里看上去不是个好主意。因此我们需要做点额外的工作,让包使用起来更像是单个模块。
(1)#### index.js
当模块的文件名是`index.js`,加载模块时可以使用模块所在目录的路径代替模块文件路径,因此接着上例,以下两条语句等价。
var cat = require('/home/user/lib/cat');
var cat = require('/home/user/lib/cat/index');
这样处理后,就只需要把包目录路径传递给`require`函数,感觉上整个目录被当作单个模块使用,更有整体感。
(2)#### package.json
如果想自定义入口模块的文件名和存放位置,就需要在包目录下包含一个`package.json`文件,并在其中指定入口模块的路径。上例中的`cat`模块可以重构如下。
- /home/user/lib/
- cat/
+ doc/
- lib/
head.js
body.js
main.js
+ tests/
package.json
其中`package.json`内容如下。
{
"name": "cat",
"main": "./lib/main.js"
}
如此一来,就同样可以使用`require('/home/user/lib/cat')`的方式加载模块。NodeJS会根据包目录下的`package.json`找到入口模块所在位置。
3.命令行执行代码
这种使用方式看起来不怎么像是一个命令行程序,下边的才是我们期望的方式。
$ node-echo Hello World
#### Linux
在Linux系统下,我们可以把JS文件当作shell脚本来运行,从而达到上述目的,具体步骤如下:
(1) 在shell脚本中,可以通过`#!`注释来指定当前脚本使用的解析器。所以我们首先在`node-echo.js`文件顶部增加以下一行注释,表明当前脚本使用NodeJS解析。
#! /usr/bin/env node
NodeJS会忽略掉位于JS模块首行的`#!`注释,不必担心这行注释是非法语句。
(2) 然后,我们使用以下命令赋予`node-echo.js`文件执行权限。
$ chmod +x /home/user/bin/node-echo.js
(3)最后,我们在PATH环境变量中指定的某个目录下,例如在`/usr/local/bin`下边创建一个软链文件,文件名与我们希望使用的终端命令同名,命令如下:
$ sudo ln -s /home/user/bin/node-echo.js /usr/local/bin/node-echo
这样处理后,我们就可以在任何目录下使用`node-echo`命令了。
#### Windows
在Windows系统下的做法完全不同,我们得靠`.cmd`文件来解决问题。假设`node-echo.js`存放在`C:\Users\user\bin`目录,并且该目录已经添加到PATH环境变量里了。接下来需要在该目录下新建一个名为`node-echo.cmd`的文件,文件内容如下:
@node "C:\User\user\bin\node-echo.js" %*
这样处理后,我们就可以在任何目录下使用`node-echo`命令了。
4.工程目录
了解了以上知识后,现在我们可以来完整地规划一个工程目录了。以编写一个命令行程序为例,一般我们会同时提供命令行模式和API模式两种使用方式,并且我们会借助三方包来编写代码。除了代码外,一个完整的程序也应该有自己的文档和测试用例。因此,一个标准的工程目录都看起来像下边这样。
- /home/user/workspace/node-echo/ # 工程目录
- bin/ # 存放命令行相关代码
node-echo
+ doc/ # 存放文档
- lib/ # 存放API相关代码
echo.js
- node_modules/ # 存放三方包
+ argv/
+ tests/ # 存放测试用例
package.json # 元数据文件
README.md # 说明文件
其中部分文件内容如下:
/* bin/node-echo */
var argv = require('argv'),
echo = require('../lib/echo');
console.log(echo(argv.join(' ')));
/* lib/echo.js */
module.exports = function (message) {
return message;
};
/* package.json */
{
"name": "node-echo",
"main": "./lib/echo.js"
}
以上例子中分类存放了不同类型的文件,并通过`node_moudles`目录直接使用三方包名加载模块。此外,定义了`package.json`之后,`node-echo`目录也可被当作一个包来使用。
5、NPM使用
### NPM
NPM是随同NodeJS一起安装的包管理工具,能解决NodeJS代码部署上的很多问题,常见的使用场景有以下几种:
+ 允许用户从NPM服务器下载别人编写的三方包到本地使用。
+ 允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。
+ 允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。
可以看到,NPM建立了一个NodeJS生态圈,NodeJS开发者和用户可以在里边互通有无。以下分别介绍这三种场景下怎样使用NPM。
#### 下载三方包
需要使用三方包时,首先得知道有哪些包可用。虽然[npmjs.org](https://npmjs.org/)提供了个搜索框可以根据包名来搜索,但如果连想使用的三方包的名字都不确定的话,就请百度一下吧。知道了包名后,比如上边例子中的`argv`,就可以在工程目录下打开终端,使用以下命令来下载三方包。
$ npm install argv
...
argv@0.0.2 node_modules\argv
下载好之后,`argv`包就放在了工程目录下的`node_modules`目录中,因此在代码中只需要通过`require('argv')`的方式就好,无需指定三方包路径。
以上命令默认下载最新版三方包,如果想要下载指定版本的话,可以在包名后边加上`@<version>`,例如通过以下命令可下载0.0.1版的`argv`。
$ npm install argv@0.0.1
...
argv@0.0.1 node_modules\argv
如果使用到的三方包比较多,在终端下一个包一条命令地安装未免太人肉了。因此NPM对`package.json`的字段做了扩展,允许在其中申明三方包依赖。因此,上边例子中的`package.json`可以改写如下:
{
"name": "node-echo",
"main": "./lib/echo.js",
"dependencies": {
"argv": "0.0.2"
}
}
这样处理后,在工程目录下就可以使用`npm install`命令批量安装三方包了。更重要的是,当以后`node-echo`也上传到了NPM服务器,别人下载这个包时,NPM会根据包中申明的三方包依赖自动下载进一步依赖的三方包。例如,使用`npm install node-echo`命令时,NPM会自动创建以下目录结构。
- project/
- node_modules/
- node-echo/
- node_modules/
+ argv/
...
...
如此一来,用户只需关心自己直接使用的三方包,不需要自己去解决所有包的依赖关系。
#### 安装命令行程序
从NPM服务上下载安装一个命令行程序的方法与三方包类似。例如上例中的`node-echo`提供了命令行使用方式,只要`node-echo`自己配置好了相关的`package.json`字段,对于用户而言,只需要使用以下命令安装程序。
$ npm install node-echo -g
参数中的`-g`表示全局安装,因此`node-echo`会默认安装到以下位置,并且NPM会自动创建好Linux系统下需要的软链文件或Windows系统下需要的`.cmd`文件。
- /usr/local/ # Linux系统下
- lib/node_modules/
+ node-echo/
...
- bin/
node-echo
...
...
- %APPDATA%\npm\ # Windows系统下
- node_modules\
+ node-echo\
...
node-echo.cmd
...
#### 发布代码
第一次使用NPM发布代码前需要注册一个账号。终端下运行`npm adduser`,之后按照提示做即可。账号搞定后,接着我们需要编辑`package.json`文件,加入NPM必需的字段。接着上边`node-echo`的例子,`package.json`里必要的字段如下。
{
"name": "node-echo", # 包名,在NPM服务器上须要保持唯一
"version": "1.0.0", # 当前版本号
"dependencies": { # 三方包依赖,需要指定包名和版本号
"argv": "0.0.2"
},
"main": "./lib/echo.js", # 入口模块位置
"bin" : {
"node-echo": "./bin/node-echo" # 命令行程序名和主模块位置
}
}
之后,我们就可以在`package.json`所在目录下运行`npm publish`发布代码了
1.express入门
var express =require('express');
var app=express();
//demo121
app.get('/demo:id',function(req,res){
//console.log(__dirname);
res.send('hello world1dddd!!'+req.params['id']);
console.log(req.cookies);
});
//app.use('/static', express.static(__dirname + '/public'));
app.use(express.static( 'public'));
// 一个简单的 logger
app.use(function(req, res, next){
console.log('%s %s', req.method, req.url);
next();
});
var server=app.listen(3000,function(){
var host=server.address().address;
var port=server.address().port;
});
2.开始
var http=require('http');
http.createServer(function(req,res){
res.writeHead(200,{'Content-Type':'text/plain'});
res.end('<h1>Hello World</h1>\n');
}).listen(80,'127.0.0.1');
2.定义模块
//模块的定义./public/js/circle.js
var PI=Math.PI;
exports.area=function(r){
return r*r*PI;
}
exports.circlePreference=function(r){
return 2*PI*r;
}
//使用
var http=require('http');
var circle=require('./public/js/circle.js');
http.createServer(function(req,res){
res.writeHead(200,{'Content-Type':'text/plain'});
res.end('<h1>Hello World</h1>\n'+circle.area(2));
}).listen(80,'127.0.0.1');
3.###`exports`
`exports`对象是当前模块的导出对象,用于导出模块公有方法和属性。别的模块通过`require`函数使用当前模块时得到的就是当前模块的`exports`对象。以下例子中导出了一个公有方法。
exports.hello = function () {
console.log('Hello World!');
};
4.#### module
通过`module`对象可以访问到当前模块的一些相关信息,但最多的用途是替换当前模块的导出对象。例如模块导出对象默认是一个普通对象,如果想改成一个函数的话,可以使用以下方式。
module.exports = function () {
console.log('Hello World!');
};
以上代码中,模块默认导出对象被替换为一个函数。
5.### 模块路径解析规则
我们已经知道,`require`函数支持斜杠(`/`)或盘符(`C:`)开头的绝对路径,也支持`./`开头的相对路径。但这两种路径在模块之间建立了强耦合关系,一旦某个模块文件的存放位置需要变更,使用该模块的其它模块的代码也需要跟着调整,变得牵一发动全身。因此,`require`函数支持第三种形式的路径,写法类似于`foo/bar`,并依次按照以下规则解析路径,直到找到模块位置。
(1) 内置模块
如果传递给`require`函数的是NodeJS内置模块名称,不做路径解析,直接返回内部模块的导出对象,例如`require('fs')`。
(2) node_modules目录
NodeJS定义了一个特殊的`node_modules`目录用于存放模块。例如某个模块的绝对路径是`/home/user/hello.js`,在该模块中使用`require('foo/bar')`方式加载模块时,则NodeJS依次尝试使用以下路径。
/home/user/node_modules/foo/bar
/home/node_modules/foo/bar
/node_modules/foo/bar
(3) NODE_PATH环境变量
与PATH环境变量类似,NodeJS允许通过NODE_PATH环境变量来指定额外的模块搜索路径。NODE_PATH环境变量中包含一到多个目录路径,路径之间在Linux下使用`:`分隔,在Windows下使用`;`分隔。例如定义了以下NODE_PATH环境变量:
NODE_PATH=/home/user/lib:/home/lib
当使用`require('foo/bar')`的方式加载模块时,则NodeJS依次尝试以下路径。
/home/user/lib/foo/bar
/home/lib/foo/bar
6.#### index.js
当模块的文件名是`index.js`,加载模块时可以使用模块所在目录的路径代替模块文件路径,因此接着上例,以下两条语句等价。
var cat = require('/home/user/lib/cat');
var cat = require('/home/user/lib/cat/index');
这样处理后,就只需要把包目录路径传递给`require`函数,感觉上整个目录被当作单个模块使用,更有整体感。
7.#### package.json
如果想自定义入口模块的文件名和存放位置,就需要在包目录下包含一个`package.json`文件,并在其中指定入口模块的路径。上例中的`cat`模块可以重构如下。
- /home/user/lib/
- cat/
+ doc/
- lib/
head.js
body.js
main.js
+ tests/
package.json
其中`package.json`内容如下。
{
"name": "cat",
"main": "./lib/main.js"
}
如此一来,就同样可以使用`require('/home/user/lib/cat')`的方式加载模块。NodeJS会根据包目录下的`package.json`找到入口模块所在位置。
8.### 工程目录
了解了以上知识后,现在我们可以来完整地规划一个工程目录了。以编写一个命令行程序为例,一般我们会同时提供命令行模式和API模式两种使用方式,并且我们会借助三方包来编写代码。除了代码外,一个完整的程序也应该有自己的文档和测试用例。因此,一个标准的工程目录都看起来像下边这样。
- /home/user/workspace/node-echo/ # 工程目录
- bin/ # 存放命令行相关代码
node-echo
+ doc/ # 存放文档
- lib/ # 存放API相关代码
echo.js
- node_modules/ # 存放三方包
+ argv/
+ tests/ # 存放测试用例
package.json # 元数据文件
README.md # 说明文件
其中部分文件内容如下:
/* bin/node-echo */
var argv = require('argv'),
echo = require('../lib/echo');
console.log(echo(argv.join(' ')));
/* lib/echo.js */
module.exports = function (message) {
return message;
};
/* package.json */
{
"name": "node-echo",
"main": "./lib/echo.js"
}
nodejs-入门教程
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- JavaScript与Node.js JavaScript与你 抛开技术,我们先来聊聊你以及你和JavaScrip...
- 1.错误:Express Command not found 最初操作:跟着《nodejs开发指南》敲npm in...
- 既然nodejs各处都体现到模块,那么这里就将数据库操作独立成一个单独的模块,之后按需加载。 在当前项目目录下新建...