Nodejs_03
3.1 Node中的模块系统
使用Node编写应用程序主要就是在使用,
- EcmaScript语言
- 和浏览器不太一样,在Node中没有BOM、DOM
- 核心模块
- 文件操作的fs
- http服务的http
- url路径操作的模块
- path路径处理模块
- os操作系统信息
- 第三方模块
- art-template
- 必须用过npm来下载才可以使用
- 自己写的模块
- 自己创建的文件
3.1.1 什么是模块化
- 文件作用域
- 通信规则
- 加载require
- 导出
(浏览器中的js做不到,node可以做到)
3.1.2 commonjs模块规范
- 模块作用域
- 使用require方法用来加载模块
- 使用exports接口对象用来导出模块的成员
main.js
var fooExports = require('./foo')
console.log(foo)
foo.js
var foo = 'bar'
function add(x,y){
return x + y
}
//有些时候希望导出仅仅是一个function,而不是通过挂载的方式,加入exports对象中
module.exports = add
//这样就可以直接在main.js里面使用fooExports就是add function
//只能得到我想要给你的成员
//这样做的目的是为了解决变量命名冲突的问题
//exports.add = add
//exports是一个对象
//我们可以通过多次为这个对这个对象添加成员实现导出多个成员
//exports.str = 'hello'
//希望加载得到的直接就是一个
//方法
//字符串
//数字
//数组
3.1.3 加载require
语法,
var 自定义变量名称 = require('模块')
两个作用
- 执行被加载模块中的代码
- 得到被加载模块中的
exports
导出接口对象
3.1.4导出exports
- Node中是模块作用域,默认文件中所有的成员只在当前文件模块有效
- 对于希望可以被其他模块访问的成员,我们就需要把这些公开的成员都挂到
exports
接口对象中就可以了- 导出多个成员(必须在对象中)
exports.a = 123 exports.b = 'hello' exports.c = function(){ console.log(`ccc`) } exports.d = { foo:'bar' }
- 导出单个成员
也可以这样拿到多个成员module.exports = 'hello' module.exports = function(x,y){ return x + y } //这里拿到的只是function,后面的会覆盖前面的定义
module exports = { add: function(){ return x + y }, str:'hello' }
如何理解exports和module
在node中,每个模块内部都有一个自己的module对象
该module对象中有一个成员是exports,是一个空对象
var module = {
exports:{
foo:'bar'
}
}
//默认在代码中还有一句
//引用类相当于直接把module.exports的地址给了exports,所以在想给module.exports直接赋值的时候,不可以直接exports = foo,只能是module.exports = foo
var exports = module.exports
expoerts/foo = 'bar'//相当于 module.exports.foo = 'bar'
//当一个模块需要导出单个成员的时候
//直接给exports赋值是不管用的
exports = 'hello'
//谁require该js文件,谁就得到module.exports对象
//默认在代码的最后有一句
return module.exports
关于如何理解值引用和类引用
var obj = {}
var obj1 = obj
obj1.foo = 'bar'
obj.foo = 'hello'
obj1 = {}
obj1.foo = 'world'
condsole.log(obj.foo)
//返回值是hello
//obj1里面同样有成员’bar‘
//重新给obj赋值就会指向另外一个对象
3.2 优先从缓存加载
main.js
require('./a')
//由于在a中已经加载过b所以之后不会重复加载
//优先从缓存加载
//可以拿到b中的接口对象,但不会重复实现里面的代码,可以提高模块加载的效率
var fn = require('./b')
console.log(fn)
a.js
console.log('a.js被加载了')
var fn = require('./b')
console.log(fn)
b.js
console.log('b.js被加载了')
module.exports = function{
console.log('hello bbb')
}
输出为
a.js被加载了
b.js被加载了
[function]
[function]
3.2.1require方法加载规则
- 路径形式的模块加载要以./(当前目录不可省略)…/(上一级目录不可省略)开头,否则就是以模块标志符形式加载
- 后缀名可以省略
- 核心模块的本质也是文件,只不过已经被编译到了二进制文件中了,我们只需要按照名字来加载
第三方模块
凡是第三方包都通过npm来下载,使用时就可以通过require(‘包名’)的方式来进行加载才可以使用
既不是核心包也不是路径形式模块,先找到
- 当前文件所处目录中的node_modules目录
- node_modules/art-template
- node_modules/art-template/package.json文件
- node_modules/art-template/package.json文件中的main属性
如果package.json文件不存在或者main指定的入口模块没有,则node会自动找改目录下的index.js,也就是说index.js会作为一个备用选项
如果以上所有任何一个条件都不成立,则会进入上一级目录中的node_modules目录查找
如果上一级还没有,则继续往上上一级查找,直到当前磁盘根目录还找不到,最后报错can not find module xxx
项目中有且只有一个node_modules,放在项目根目录中,这样的话,项目中所有的子目录中的代码都可以加载到第三方包
每个项目都需要一个package.json文件来说明该项目依赖了哪个包
在该项目的root中下载第三方包的时候要加上
npm install art-tempalte jquery --save
//或者
npm install --save art-template jquery
//就会自动把依赖的包信息放进package.json文件中去
//我们也不需要自己手动生成package.json文件可以在项目root中通过命令行
npm init
//entry point文件执行的入口,因为node每次只会执行一个文件,所以要指明是那个文件最开始执行
//没有的东西就直接entry键跳过
//当你误删了node_modules的时候,如果你有package.json文件可以直接通过
npm install
//来找回以前的package
3.3 npm常见命令
- npm init
- npm init -y 可以跳过向导,快速生成
- npm install 包名 --save
- npm uninstall 包名 (只删除,如果有依赖项会依然保存)
- npm uninstall 包名 --save (删除同时如果有依赖信息也删除)
- npm help
- npm 命令 --help(查看具体命令的使用说明)
3.3.1 解决npm被墙的问题
npm存储包文件的服务器在国外,有点时候会被墙
cnpm镜像 淘宝npm镜像
// -- global 表示安装到全局而并非当前目录
npm install --global cnpm
接下来你安装包的时候吧之前的npm
替换成cnpm
cnpm install jquery
如果不想安装cnpm
也想使用镜像的话可以以用
npm install jquery --registry=http://registry.npm.taobao.org
也可以通过把这个选项加入配置文件中
npm config set registry http://registry.npm.taobao.org
#验证配置是否成功
npm config list
3.4 express
原生的http在某些方面表现不足以应对我们的开发需求,所以我们就需要使用框架来就加快我们的开发效率,框架的目的就是提高效率,让我们的代码更高度统一
在node中有很多Web开放框架,我们这里以学习express为主
express官网
安装
mkdir express_demo
cd express_demo
npm init -y
npm i -S express
var express = require('express')
var app = express()
//在express中开放资源就是一个API的事儿
//公开指定目录
//只要这样做了,你就可以直接通过/public/xx的方式访问public目录中的所有资源了
app.use('/public/',express.static('./public'))
//模板引擎也是一个API
app.get('/',function(req,res){
res.send('hello express')
})
app.get('/about',function(req,res){
res.send('你好我是 express')
})
app.listen(3000,function(){
console.log('app is running at port 300')
})