5.模块系统
使用node编写用用程序,主要就是在使用:
- EcmaScript语言
- 核心模块
- 文件操作fs
- http服务的http
- url路径操作模块
- path路径处理模块
- os操作系统信息
- 第三方模块
- art-template 等
- 通过npm来下载使用
- 自定义模块
5.1什么是模块化
- 文件作用域
- 通信规则
- 加载require
- 导出exports
5.2加载与导出
5.2.1加载
语法:
var 自定义变量名称 = require('模块')
若是官方包或者第三方包,引号内直接写包名,若是自定义包,需要写路径。为保证文件可移植性,尽量用相对路径。
两个作用:
- 执行被加载模块中的代码
- 得到被加载模块中的
exports
导出接口对象
注意:加载过一次不会被重复加载。如
a.js
console.log('load a')
require('./b')
b.js
console.log('load b')
main.js
require('./a')
require('./b')
运行main.js,结果为,仅加载b一次。目的是加载其中的接口函数,而不重复加载
load a
load b
5.2.2导出
-
node中为模块作用域,默认文件中所有成员只在当前文件模块有效
-
对于希望可以被其他模块访问的成员,需要将其挂载到
exports
接口对象中-
导出多个成员,见3.2
-
导出单个对象
a.js
var bExorts = require('./b') console.log(bExorts(10,50))
b.js
function add(x,y){ return x+y } module.exports = add
运行结果60
-
5.2.3理解
-
exports
和module.exports
一样,相当于模块最早有一句
var exports = module.exports
,最后有一句:
return module.exports
-
第三方包和核心模块必然不同名
-
加载过程
- 先找到当前目录中的node_modules目录
- 找其中对应包名的目录如 node_modules/art-template
- 找该目录下的package.json文件,文件里的main指定一个js的入口模块,加载。若没有指定,则找index.js文件加载
- 若以上接不成立,则去上一级目录查找,规则同上
- 重复4直到当前磁盘根目录
- 最后报错can not find …
也就是说,一个项目,只需要在项目的根目录安装需要的包即可。
5.3npm (node package manager)
5.3.1npm网站
www.npmjs.com
5.3.2npm命令行工具
npm -v
或npm -verion
查看版本
5.3.3常用命令
- npm init
- npm init -y 可以跳过向向导,快速生成
- npm install
- 一次性把dependencies选项中的依赖项全部安装
- npm -i
- npm install 包名
- 只下载
- npm i 包名
- npm install --save 包名
- 下载并且保存依赖项
- npm i -S 包名
- npm uninstall 包名
- 只删除,如有依赖项仍保留
- npm un -S 包名
- npm uninstall 包名 --save
- npm help
- 查看帮助
- npm 命令 --help
- 查看具体命令的使用帮助
5.3.4 解决npm被墙问题
npm储存包文件服务器在国外,容易速度慢,淘宝开发做了一个镜像。
http://npm.taobao.org/
安装cnmp:
npm install --global cnpm
之后把npm改成cnpm即可
5.4 package.json
-
建议每个项目需要一个package.json文件,即包描述文件,其中指示该项目中的依赖项。
-
可以在npm中用
npm init
命令新建文件,有后续一系列设定。会自动生成package.jsonPS G:\code\nodejs> npm init This utility will walk you through creating a package.json file. It only covers the most common items, and tries to guess sensible defaults. See `npm help json` for definitive documentation on these fields and exactly what they do. Use `npm install <pkg>` afterwards to install a package and save it as a dependency in the package.json file. Press ^C at any time to quit. version: (1.0.0) description: for test entry point: (a.js) test command: git repository: keywords: author: cwd license: (ISC) About to write to G:\code\nodejs\package.json: { "name": "test", "version": "1.0.0", "description": "for test", "main": "a.js", "dependencies": { "art-template": "^4.13.2" }, "devDependencies": {}, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "cwd", "license": "ISC" } Is this OK? (yes) y
-
安装第三方包时,建议加上–save,如
npm i art-template --save
,会自动将依赖描述添加到package.json中 -
当拥有package.json时,若丢失node_modules文件夹,则运行
npm install
会将kackage.json中的依赖项全部都装回来。
6.Express
原生的http在某些方面表现不足以应对我们的开发需求。使用框架来提高开发效率。
6.1 hello express
//引包
var express = require('express')
//创建服务器应用程序
//就是原来的 http.creatserver
var app = express()
//当服务器收到get请求,执行回调处理函数
app.get('',function(req,res){
res.send('hello express!')
})
//相当于server.listen
app.listen(3000,function(){
console.log('running')
})
6.2几个基本操作
var express = require('express')
var app = express()
//提供静态资源目录
//可以直接通过/public/xx的方式访问public目录中的所有资源
app.use('/public/',express.static('./public/'))
app.get('/',function(req,res){
res.send(`
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title> document</title>
</head>
<body>
<h1>hello</h1>
</body>
</html>
`)
})
//相当于server.listen
app.listen(3000,function(){
console.log('running')
})
6.2.1基本路由
路由器
- 请求方法
- 请求路径
- 请求处理函数
get:
//以get方法请求/的时候,执行对应的处理函数
app.get('/',function(req,res){
res.send('hello world')
})
post:
//以post方法请求/的时候,执行对应的处理函数
app.post('/',function(req,res){
res.send('hello world')
})
6.2.2 静态资源开放
https://www.expressjs.com.cn/starter/static-files.html
//公开public文件夹下内容,并假设要访问其中a.js
// 127.0.0.1:3000/a.js
app.use(express.static('public'))
// 127.0.0.1:3000/public/a.js
app.use('/public',express.static('public'))
// 127.0.0.1:3000/static/a.js
app.use('/static',express.static('public'))
6.2.3配置art-template
http://aui.github.io/art-template/express/
安装:
npm install --save art-template
npm install --save express-art-template
express-art-template专门用来在Express中把art-template整合进去
因为其依赖art-template,故也需要安装
配置:(example)
var express = require('express');
var app = express();
// view engine setup
app.engine('art', require('express-art-template'));
app.set('view', {
debug: process.env.NODE_ENV !== 'production'
});
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'art');
// routes
app.get('/', function (req, res) {
res.render('index.art', {
user: {
name: 'aui',
tags: ['art', 'template', 'nodejs']
}
});
});
使用:
//Express为Response相应对象提供了一个方法:render
//render方法默认不可以使用,但是如果配置了模板引擎就可以使用
//res.render('html模板名',{模板数据})
//第一个参数不能写路径,默认会去项目中的views目录查找改模板文件
//也即Express约定,开发人员把所有视图文件放到views目录中
app.get('/',function(req,res){
res.render('index.html')
})
如果试图修改默认路径:
app.set('views',目录路径)
6.3在Express中获取表单post请求数据
需要第三方包,body-parser
https://www.expressjs.com.cn/en/resources/middleware/body-parser.html
安装:
npm install body-parser
配置:
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
// 只要加入这个配置,则在req对象上会多出来一个属性:body
//即直接通过req.body来获取表单post请求数据
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
//使用:
app.use(function (req, res) {
res.setHeader('Content-Type', 'text/plain')
res.write('you posted:\n')
res.end(JSON.stringify(req.body, null, 2))
})