Node的模板系统
06.模块系统
在node中JavaScript还有一个很重要的概念:模块系统
- 模块作用域
- 使用require方法用来加载模块
- 使用exports 接口对象用来到处模块中的成员
1.加载
语法:require
俩个作用:1
const 自定义变量名称 = require('模块')
- 执行被加载模块中的代码
- 得到被加载模块中的
exports
导出接口对象2.导出
exports
- node中的模块作用域,默认文件中所有成员只在当前文件模块有效
- 对于希望可以被其他模块访问的信息,我们就需要把这些公共的成员都挂载到
exports
接口对象中就可以导出多个成员(必须在对象中)
导出多个成员(必须在对象中:此时exports是个对象):
1 |
|
导出单个成员(就是拿到:函数,字符串等)
1 |
|
以下情况会覆盖:最下边会覆盖上边的
1 |
|
也可以导出多个成员:就是把它变为对象了
1 |
|
3.导出 module.exports
原理解析
exports
和 module.exports
的一个引用
内部隐藏代码实际是这样子的:
1 |
|
4.exports 和 module.exports 的 区别
每个模块中都有一个
module
对象module
对象中都有一个exports
对象我们可以把需要导出的成员都挂载到
module.exports
接口对象中也就是,
module.exports.xxx= xxx
的方式但是每次都
module.exports.xxx = xxx
很麻烦所以 node 为了使用方便, 同时在每一个模块中都提供了一个成员叫
exports
exports = module.exports
结果为 true 就证明了此点所以对于:
module.exports.xxx= xxx
的方式完全可以exports.xxx= xxx
当每一个模块需要导出单个成员的时候,这个时候必须使用:
module.exports= xxx
的方式,不要使用
exports = xxx
不管用因为每个模块最终向外
return
的是module.exports
而
exports
只是module.exports
的一个引用所以即便你为
exports =xxx
重新赋值,也不会影响到module.exports
但是有一种赋值比较特殊 :
exports = module.exports
这个可以重新建立引用关系5.模块查找机制
自己的定义的模块 (路径形式的模块)
- 自定义模块形式的书写:
- ./ 代表 当前目录,不可省略
- ../ 代表 上一级目录, 不可省略
- /xxx 和 d:/a/foo.js 这种形式的 不用
- 首位的 / 在这里表示的是当前文件模块所属磁盘根路径
- .js 后缀名可以省略
- require(‘./foo.js’)
优先从缓存加载
核心模块
- 核心模块已经被编译到了二进制二文件中,我们只需要按照名字来加载模块就可以了
- require(‘fs’)
- require(‘http’)
第三方模块
- 查找步骤:以为 第三方
express
模块为例 - node_modules/express/
- node_modules/express/package.json
- node_modules/express/package.json/文件中找main属性
- 如果找不到main属性 就 默认 index.js 为备选项
- 以上找不到 就 进入上一级目录 node_modules 再次查找
- 按照这个规则依次往上找,类似于
js中的原型链
, 直到磁盘根目录还找不到,就会报错 :cannot find module xxxx
- 查找步骤:以为 第三方
6.npm
- node package manager 意思就是 node 包管理者,帮助我们去安装一些第三方包的
6.1npm 网站
- [npmjs.com] 用来搜索第三方包, 所有的第三方包都在这里
6.2 npm命令行工具
- npm 的第二次含义就是一个命令行工具,只要你安装了 node 就已经安装了npm
- npm也有版本这个概念 可以通过在命令行中输入 查看版本号
1
2npm --version //查看版本号
npm install --global npm // 升级npm6.3解决npm被墙的问题
npm存储包文件的服务器在国外,有时候会被强,速度会很慢。 - [http://npm.taobao.org/] 淘宝的开发团队把npm在国内做了一个备份
- 安装淘宝的npm接下来你安装包的时候把之前的
1
2
3# 在任意目录执行都可以
# -- global 表示安装到全局, 而非当前目录 注意不能省略 --global
npm install --global cnpmnpm
替换成cnpm
就行了如果不想安装1
2
3
4# 这里 还是走国外的服务器,速度慢
npm install jquert
# 使用cnpm 就会通过淘宝的服务器来下载jquery
cnpm install jquertcnpm
又想使用淘宝的服务器下载:但是每一次手都这样会很麻烦,所有可以把这个选项加入配置文件中1
npm install jquery --registry=https://registry.npm.taobao.org
只要经过上面的命令配置,则以后你所有的1
2
3npm config set registry https://registry.npm.taobao.org
# 查看npm配置信息
npm config listnpm install
都会默认通过淘宝的服务器来下载
7.package.json
- 我们建议每一个项目都需要有一个
package.json
文件(包描述文件,就像产品的说明书一样) - 这个文件可以通过
npm init
的方式来自动化出来, 但现在的版本都可以自动生成了。 - 对于我们新手来说,最有用的是
dependencies
选项,可以用来帮我们保存第三方包的依赖信息 - 如果你的
node_module
删除了也不用担心,我们只需要:npm install
就会自动把package.json
中的dependencies
中所有依赖项都会下载回来 - 要求每个项目的根目录下都有一个
package,json
文件 - 建议执行
npm install 包名
时候 都加上--save
(新版本也就不用啦) 来保存依赖项信息
7.1 package-lock.json 和 package.json
npm 5 版本 以前是不会有 package-lock.json
这个文件
npm 5 版本之后才加入这个文件
当你安装包的时候,npm都会生成或者更新 package-lock.json
这个文件
- npm 5版本以后的 安装包不需要加
--save
参数就会自动保存依赖信息 - 当你安装包的时候,会自动创建或者是更新
package-lock.json
这个文件 package-lock.json
这个文件会保存node_modules
中所有包的信息(版本,下载地址等)- 这样的话,重新
npm install
的时候 速度会提升
- 这样的话,重新
- 从文件名来看
lock
称 为 锁 - 文件操作路径
1
2
3
4
5
6
7
8
9
10
11// 在文件操作的相对路径中
// ./data/a.txt 相当于当前目录
// data/a.txt 相当于当前目录
// 以下俩种几乎不用 (不要用)
// /data/a.txt 绝对路径,当前文件模块所处磁盘根目录
// c;/xx/xx 绝对路径
fs.readFile('./data/a.txt',(err)=>{data}){
}
- 模块操作路径
1
2
3
4
5// 如果这里忽略了 . 则也是磁盘根目录
require('/data/foo.js')
// 相当路径 在模块路径中 一定不能省略 ./
require('./data/foo.js')9.nodemon 修改代码自动重启服务器
- 我们这里可以使用一个nodemon 第三方命令行工具 来解决我们频繁修改代码重启服务器的问题
nodemon
是一个基于Node.js开发的一个第三方命令行工具,需要独立安装1
2#在任意目录中执行该命令都行
npm install --global nodemon- 安装完毕后,使用:
1
2# 使用nodemon
nodemon app.js10.path 路径操作模块
- path.basename
- 获取一个路径的文件名 (默认包含扩展名)
1
2
3
4
5> path.basename('c:/a/b/c/index.js')
'index.js'
> path.basename('c:/a/b/c/index.js','.js')
'index'
- 获取一个路径的文件名 (默认包含扩展名)
- path.dirname
- 获取一个路径中的目录部分
1
2> path.dirname('c:/a/b/c/index.js')
'c:/a/b/c'
- 获取一个路径中的目录部分
- path.extname
- 获取一个路径中的扩展名部分
1
2> path.extname('c:/a/b/c/index.js')
'.js'
- 获取一个路径中的扩展名部分
- path.pars
- 把一个路径转为对象
- root 根路径
- dir 目录
- base 包含后缀名的文件名
- ext 后缀名
- name 不包含后缀名的文件名
1
2
3
4
5
6
7
8> path.parse('c:/a/b/c/index.js')
{
root: 'c:/',
dir: 'c:/a/b/c',
base: 'index.js',
ext: '.js',
name: 'index'
}
- 把一个路径转为对象
- path.join
- 当你需要进行路径拼接的时候, 推荐使用
1
2> path.join('c:/a','b')
'c:\\a\\b'
- 当你需要进行路径拼接的时候, 推荐使用
- path.isAbsolute
__dirname
动态获取 可以用来获取当前文件的所属目录的绝对路径 (这个没有加文件 只是文件的绝对目录)__filename
动态获取 可以用来获取当前文件的绝对路径 (这个加上了文件)-
__dirname
和__filename
是不受执行node命令所属路径影响的
在文件操作中,使用相对路径是不可靠的,因为在Node 中 文件操作 的路径被设计为相对于执行node命令所处的路径(不是bug,人家这样设计是有使用场景)
所以为了解决这个问题,只需要把 相对路径变为绝对路径 就可以了
所以我们可以使用__dirname
和__filename
来帮我们解决这个问题
在拼接路径过程中,为了 避免手动凭借带来的一些低级错误, 我们推荐使用: path.join()
来辅助拼接。
所以为了尽量避免刚才所描述的问题,以后必须在文件操作中使用相对路径都统一转换为 动态的绝对路径
注意: 模块中的路径标识 和 文件操作 中的 相对路径标识 不一致
模块中的路径表示就是相当于当前文件模块,不受执行node 命令所处路径影响