Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。
① 基于 Express 框架(http://www.expressjs.com.cn/),可以快速构建 Web 应用
② 基于 Electron 框架(https://electronjs.org/),可以构建跨平台的桌面应用
③ 基于 restify 框架(http://restify.com/),可以快速构建 API 接口项目
④ 读写和操作数据库、创建实用的命令行工具辅助前端开发、etc…
1 基本命令
1.1 查看版本
node -v
1.2 执行指定js文件
node 1.\ 测试.js
node 文件路径
2 文件模块
2.1 导入文件模块
const fs = require('fs')
2.2 读取文件
fs.readFile(path[, options], callback)
- 参数1:必选参数,字符串,表示文件的路径。
- 参数2:可选参数,字符串, 表示以什么编码格式来读取文件。
- 参数3:必选参数,文件读取完成后,通过回调函数拿到读取的结果。
const fs = require('fs')
fs.readFile('./files/q.txt', 'utf8', function (err, dataStr) {
console.log(err);
console.log('-------');
console.log(dataStr);
})
没有异常err 为 null
错误结果:
判断读取文件失败输出错误结果:
const fs = require('fs')
fs.readFile('./files/q1.txt', 'utf8', function (err, dataStr) {
if (err) {
return console.log(err.message);
}
console.log(dataStr);
})
2.3 写入文件
fs.writeFile(file, data[, options], callback)
- 参数1:必选参数,需要指定一个文件路径的字符串,表示文件的存放路径。
- 参数2:必选参数,表示要写入的内容。
- 参数3:可选参数,表示以什么格式写入文件内容,默认值是 utf8。
- 参数4:必选参数,文件写入完成后的回调函数。
const fs = require('fs')
fs.writeFile('./files/2.txt', 'hello nodejs', err => {
if(err) {
return console.log(err.message);
}
console.log(err);
})
同读取一样,若是无异常, err为null
注意:
3.1 路径动态拼接问题
开头的相对路径时,很容易出现路径动态拼接错误的问题。
代码在运行的时候,会以执行 node 命令时所处的目录,动态拼接出被操作文件的完整路径。
console.log(__dirname + '/xxxx');
3.2 路径拼接方法—join
用来将多个路径片段拼接成一个完整的路径字符串
path.join([...paths])
- …paths
路径片段的序列 - 返回值:
../ 会抵消一层路径
const path = require('path')
const self_path = path.join(__dirname, './files/1.txt')
console.log(self_path);
3.3 获取文件名—basename
可以从一个文件路径中,获取到文件的名称部分
path.basename(path[, ext])
- path
必选参数,表示一个路径的字符串 - ext
可选参数,表示文件扩展名 - 返回:
表示路径中的最后一部分
const path = require('path')
var p = 'a/b/c/index.js'
console.log(path.basename(p));
console.log(path.basename(p, '.js'));
3.4 获取扩展名—extname
可以获取路径中的扩展名部分
path.extname(path)
path
返回:
const path = require('path')
var p = 'a/b/c/index.js'
console.log(path.extname(p));
3.5 综合运用
目标抽出html里面的style标签和script标签的内容分别放入其他文件中
1 创建正则表达
const fs = require('fs')
const path = require('path')
// 匹配<style></style>和<script></script>标签内容
const regStyle = /<style>[\s\S]*<\/style>/;
const regScript = /<script>[\s\S]*<\/script>/;
\S匹配非空字符串
[] 表示有一系列字符可供选择,只要匹配其中一个就可以了
*表示任意次
2 读取与写入
fs.readFile(path.join(__dirname, './index.html'), 'utf8', (err, result) => {
if (err) return console.log(err.message);
resolve(result, '<style>', '</style>', regStyle, './clock/index.css');
resolve(result, '<script>', '</script>', regScript, './clock/index.js');
resolveHTML(result);
})
// 抽出css和js
function resolve(result, relc1, relc2, reg, target_path) {
var str = reg.exec(result);
// 去除首尾style标签
var newCSS = str[0].replace(relc1, '').replace(relc2, '');
// 写入文件中
fs.writeFile(path.join(__dirname, target_path), newCSS, err => {
if (err) return console.log(err.message);
console.log('write file success');
})
}
// 去掉内联的css和js
function resolveHTML(params) {
const newHTML = params
.replace(regStyle, '<link rel="stylesheet" href="./clock/index.css">')
.replace(regScript, '<script src="./clock/index.js"></script>');
fs.writeFile(path.join(__dirname, './index.html'), newHTML, err => {
if (err) return console.log(err.message);
console.log('write file success');
})
}
4 http模块
可以说一台服务器可以开启多个web网站服务,只是端口号不同
4.1 创建web服务器
① 导入 http 模块
const http = require('http')
② 创建 web 服务器实例
const server = http.createServer()
③ 为服务器实例绑定 request 事件,监听客户端的请求
server.on('request', (req, res)=>{
console.log('have people come in');
})
④ 启动服务器
server.listen(80, () => {
console.log('start the server');
})
4.2 请求对象与响应对象
const http = require('http')
const server = http.createServer()
server.on('request', (req, res) => {
const str = `请求url:${req.url}, 请求类型:${req.method}`;
res.setHeader('Content-Type', 'text/html; charset=utf-8')
res.end(str)
})
server.listen(80, () => {
console.log('http://localhost');
})
4.3 解决响应中文乱码
需要手动设置内容的编码格式
res.setHeader('Content-Type', 'text/html; charset=utf-8')
4.4 动态响应案例
const http = require('http')
const server = http.createServer()
server.on('request', (req, res) => {
const url = req.url; // 获取请求url地址
let content = '<h1>404 你所访问资源已被冲入厕所</h1>'
if (url === '/' || url === '/index.html') {
content = '<h1>首页</h1>'
}
res.setHeader('Content-Type', 'text/html; charset=utf-8')
res.end(content)
})
server.listen(80, () => {
console.log('http://localhost');
})
4.4 访问静态网页
const fs = require('fs')
const http = require('http')
const path = require('path')
const server = http.createServer();
server.on('request', (req, res) => {
let content = '<h1>404 你所访问资源已被冲入厕所</h1>';
let fpath = ''
if (req.url === '/') {
fpath = path.join(__dirname, './index.html');
} else {
fpath = path.join(__dirname, req.url)
}
fs.readFile(fpath, 'utf8', (err, data) => {
if (err) {
res.setHeader('Content-Type', 'text/html; charset=utf-8');
return res.end(content);
}
res.end(data);
})
})
server.listen(80, () => {
console.log('start http://localhost');
})
5 模块化
模块化是指解决一个复杂问题时,自顶向下逐层把系统划分成若干模块的过程。对于整个系统来说,模块是可组合、分解和更换的单元。
把代码进行模块化拆分的好处:
① 提高了代码的复用性
② 提高了代码的可维护性
③ 可以实现按需加载
5.1 引入模块问题
使用 require() 方法加载其它模块时,会执行被加载模块中的代码。
文件 12.模块引入.js:
// 将被引入模块
console.log('12');
导入模块的文件
const x = require('./12.模块引入')
console.log(x);
5.2 模块作用域
在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问,这种模块级别的访问限制,叫做模块作用域。
好处是为了防止全局变量污染。
不同于浏览器,导入文件所含的全局变量都在window对象中,容易造成覆盖即全局变量污染。
5.3 module对象
每个 .js 自定义模块中都有一个 module 对象,它里面存储了和当前模块有关的信息
console.log(module)
5.4 共享模块成员
在自定义模块中,可以使用 module.exports 对象,将模块内的成员共享出去,供外界使用。
外界用 require() 方法导入自定义模块时,得到的就是 module.exports 所指向的对象。
var a = 10
function sayHi(params) {
console.log('hello world');
}
module.exports.a = a;
module.exports.sayHi = sayHi
const x = require('./14 module对象')
console.log(x);
x.sayHi()
require() 模块时,得到的永远是 module.exports 指向的对象
module.exports 可以不用写module
为了防止混乱,不要在同一个模块中同时使用 exports 和 module.exports
默认情况下,exports 和 module.exports 指向同一个对象。
最终共享的结果,还是以 module.exports 指向的对象为准。
5.5 CommonJS规范
CommonJS 规定了模块的特性和各模块之间如何相互依赖。
CommonJS 规定:
① 每个模块内部,module 变量代表当前模块。
② module 变量是一个对象,它的 exports 属性(即 module.exports)是对外的接口。
③ 加载某个模块,其实是加载该模块的 module.exports 属性。require() 方法用于加载模块。