文章目录
1.什么是node.js
1-1.初识node
1. Node.js是一个基于Chrome V8 引擎的JavaScript 运行环境
2. node.js中文网址:http://www.nodejs.cn/
1-2.node.js的JavaScript运行环境
- 图解
1-3.学习路线
1. Node.js内置模块(fs,path,http等)+ 第三方API模块(express、mysql等)
1-4.终端里的快捷键
1. ↑ 快速定位到上一次使用过的命令
2. tab 快速补全路径
3. esc 快速清空已经输入过的命令
4. cls 快速清空终端
2.fs文件系统模块
2-1.文件读取fs.readFile()
1. 语法格式:fs.readFile( ’ 路径 ’ ,’ 编码格式 ‘,’ 回调函数 ’ );
代码演示:
// 导入fs模块,用来操作文件
const fs =require('fs');
// fs.readFile('路径' ,'utf8', 回调函数)
fs.readFile('../被读取.js' ,'utf8',function(err,dataStr){
if(err){
console.log('文件读取失败' + err.message);
}else{
console.log('文件读取成功,内容是:' + dataStr );
}
})
读取成功:
读取失败:
2-2.文件写入fs.writeFile()
1. 语法格式:fs.writeFile( ’ 路径 ’ ,’ 写入内容 ’ , ’ 编码格式 ‘,’ 回调函数 ’ );
代码演示:
// 导入fs文件模块
const fs = require('fs');
// 语法格式:fs.writeFile('路径' , '内容' , ' 编码格式可以省略' , '回调函数' )utf8的编码格式
fs.writeFile('../被读取.js' , '222' , function(err){
// err的值等于null表示写入成功
// 写入失败值就等于一个错误对象
if(err){
console.log('文件写入失败:' + err.message);
}else{
console.log('文件写入成功');
}
})
写入成功:
写入失败:
2-3.路径动态拼接
1.用./或者…/相对路径会出现找不到地址的情况
2. 直接用__dirname + ’ 路径地址 ’ ,就完成了路径的动态拼接
格式如下:
// 导入fs文件模块
const fs = require('fs');
// 语法格式:fs.writeFile('路径' , '内容' , ' 编码格式可以省略' , '回调函数' )utf8的编码格式
fs.readFile(__dirname + '../../00.公共资源/被读取.js' , function(err,dataStr){
// err的值等于null表示写入成功
// 写入失败值就等于一个错误对象
if(err){
console.log('文件读取失败:' + err.message);
}else{
console.log('文件读取成功:' + dataStr);
}
})
结果展示:
3.path路径模块
3-1.什么是path路径模块
1. path 模块是node.js 官方提供的、用来处理路径的模块。提供了一系列的方法和属性来满足用户的需求
2. path.join()方法、用来将多个路径片段拼接成一个完整的路径字符串
3. path.basename()方法、用来从路径字符串中将文件名解析出来
4. 使用之前得像fs模块一样导入(const path = require(’ path '))
3-2.路径拼接path.join()的语法格式
代码演示:
const path = require('path');
const fs = require('fs');
fs.readFile(path.join(__dirname,'../files/1.txt'), 'utf8' , function(err,dataStr){
if(err){
console.log(err.message);
}else{
console.log(dataStr);
}
})
展示结果:
3-2.获取路径文件名path.basename()的语法格式
代码演示:
const path = require('path');
const fpath = '/1/2/3/index.html';
const fullname = path.basename(fpath);
console.log(fullname);
const houzui = path.basename(fpath,'.html');
console.log(houzui);
展示结果:
3-2.路径后缀path.extname()的语法格式
代码演示:
const path = require('path');
const fpath = '/1/2/3/index.html';
const ext = path.extname(fpath);
console.log(ext);
展示结果:
4.http模块
4-1.创建web服务器
1. 导入http模块
2. 创建wwweb服务器
3. 为服务器实例绑定request事件、监听客户端的请求
4. 启动服务器
代码演示:
// 一、导入http模块
const http = require('http');
// 二、创建wwweb服务器
const server = http.createServer();
// 三、为服务器实例绑定request事件、监听客户端的请求
server.addListener('request',(req,res)=>{
console.log('有人访问服务器');
})
// 四、启动服务器
server.listen(80,()=>{
console.log('服务器运行在80端口');
})
展示结果:
4-2.req请求对象(url和method)
代码演示:
const http = require('http');
const server = http.createServer();
server.addListener('request',(req,res)=>{
console.log('有人访问服务器');
const url = req.url;
const method = req.method;
const str = '你的请求地址是' + url + '你的请求方式是' + method;
console.log(str);
})
server.listen(80,()=>{
console.log('服务器运行在80端口');
})
结果展示:
4-3.res.end ---- 返回给客户端信息
代码演示:
const http = require('http');
const server = http.createServer();
server.addListener('request',(req,res)=>{
const str = '你的请求地址是' + req.url + '你的请求方式是' + req.method;
console.log(str);
// 防止中文乱码
res.setHeader('Content-Type','text/html:charset=utf-8');
// res.end返回给客户端一些信息
res.end(str);
})
server.listen(80,()=>{
console.log('服务器运行在80端口');
})
结果展示:
4-4.乱码问题
- res.setHeader(‘Content-Type’,‘text/html:charset=utf-8’);
4-5.根据不同的url响应不同的内容
- 获取请求url地址
- 设置默认相应内容为404 Not found
- 判断用户请求是否为 / 或者 /index.html首页
- 判断用户请求是否为/iabout.html关于页面
- 设置Content-Type响应头,防止中文乱码
- 使用res.end()把内容响应给客户端
代码演示:
const http = require('http');
const server = http.createServer();
server.addListener('request',(req,res)=>{
const url = req.url;// 1. 获取请求url地址
// 2. 设置默认相应内容为404 Not found
let content = '<h1>404 Not found</h1>'
// 3. 判断用户请求是否为 / 或者 /index.html首页
if(url === '/' || url === '/index.html'){
content = '<h1>首页</h1>'
}else if(url==='/about.html'){
content = '<h1>关于</h1>'
}
// 4. 判断用户请求是否为/iabout.html关于页面
// 5. 设置Content-Type响应头,防止中文乱码
res.setHeader('Content-Type','text/htm;charset=utf-8');
// 6. 使用res.end()把内容响应给客户端
res.end(content);
})
server.listen(80,()=>{
console.log('服务器地址是:localhost');
})
结果展示:
5.模块化
5-1.模块化分类
1. 内置模块(fs,path,http等)
2. 自定义模块(自己创建的)
3. 第三方模块(由第三方开发出来的模块,使用前需要先下载)
5-2.加载模块
// 1. 加载内置模块
const fs = require('fs')
// 2. 加载自定义模块,.js可以省略
const person = require('./person.js')
// 3. 加载第三方模块
const out = require('out')
5-2.模块化作用域
1. 和函数作用域相似,在自定义模块中定义的变量、方法,只能在当前模块内被访问,这种模块级别的访问限制叫做模块作用域
2. 可以防止全局变量污染的问题
5-3.module对象
1. 在每个js自定义模块中都有一个module对象,它里面储存了和当前模块有关的信息,打印如下:
5-4.module.exports对象
1. 向外共享成员
2. 用require()方法导入结果时,永远以module.exports指向的对象为准
5-5.exports对象
1. 和module.exports指向的对象一样
5-5.exports和module.exports的使用误区
1. 用require()方法导入结果时,永远以module.exports指向的对象为准
5-6.Node.js中的模块化规范
CommonJS规定:
1. 每个模块内部,module变量代表当前模块
2. module变量是一个对象,它的exports属性(module.exports)是对外的接口
3. 加载某个模块,其实是加载该模块的module.exports属性,require()方法用于加载模块
6.npm与包
6-1.包的概念
6-1-1.什么是包
- Node.js中的第三方模块又叫做包
6-1-2.包的来源
- 包是由第三方个人或者团队开发出来的.免费供给所有人使用
6-1-3.为什么需要包
- 包是基于内置模块封装出来的,提供了更高级,更方便的API,极大的提供了开发效率
6-1-4.包共享平台
6-1-5.如何下载包
- 包管理工具npm,安装node的时候自动安装了,使用npm -v查看版本
6-2.包的使用演示
6-2-1.传统方式实现时间格式化
6-2-1-1.自定义模块
6-2-1-2.initTime.js
结果展示:
6-2-2.实现时间格式化高级用法
6-2-2-1.实现步骤
- 使用npm包管理工具,在项目中安装格式化时间的包moment
- 使用require()导入格式化时间的包
- 参考moment的官方API文档对时间进行格式化
6-2-2-2.在项目中安装包的命令
- npm install 包名称
- npm i 包名称
6-2-2-3.实现
官方文档:
代码演示:
var moment = require('moment'); // require
var initTime = moment().format('YYYY-MM-DD HH:mm:ss');
console.log(initTime);
结果展示:
6-3.使用npm的注意点
6-3-1.装包完成过后
- 装包完成后项目文件夹中会多一个叫做node_modules的文件夹和package-lock.json的配置文件
- package-lock.json的配置文件用来记录node_modules目录下的每一个包的下载信息,例如包的名字、版本号、下载地址等
6-3-2.安装指定版本的包
- npm install 包名称@版本号
6-3-3.包管理配置文件package.json
- npm规定,在项目根目录中,必须提供一个叫做package.json的包管理配置文件,用来记录与项目有关的一些配置信息
- 项目名称、版本号、描述等
- 项目中都用到了哪些包
- 哪些包只在开发中会用到
- 哪些包在开发和部署时都需要用到
6-3-4.如何记录项目中安装了哪些包(快速创建package.json)
- npm包管理工具提供了一个快捷命令,可以在执行命令时所处的目录中,快速创建package.json这个包管理配置文件
- npm init -y (首先用在项目文件夹中)
- 这个命令只能用在英文目录下
6-3-5.dependencies节点
- package.json文件中,有一个dependencies节点,专门用来记录使用npm install命令安装了哪些包
6-3-6.一次性安装所有的包
- npm install 一次性安装所有的依赖包
- 执行npm install 命令时,npm包管理工具会读取 package.json 中的 dependencies 节点
- 读取到记录的所有依赖包名称和版本号之后,npm管理工具会把这些包一次性下载到目录中
6-3-7.卸载包
- npm uninstall 包名称
6-3-8.devDependencies节点
- 如果某些包只在项目开发阶段会用到,在项目上线之后不会用到,则建议把这些包记录到devDependencies节点中
6-3-9.安装到devDependencies节点中的两种方法
- npm install 包名 -D
- npm install 包名 --save–dev
6-3-10.下载包速度慢的解决方法
6-3-10-1.安装淘宝镜像
- npm install -g cnpm -registry=https://registry.npm.taobao.org
6-3-10-2.切换npm的下包镜像源
- 查看当前的下包镜像源 npm config get registry
- 将下包的镜像切换为淘宝镜像源 npm config set registry=https://registry.npm.taobao.org
- 检查镜像源是否下载成功 npm config get registry
6-3-10-3.nrm
- 为了方便切换下包的镜像源,我们可以安装nrm这个小工具,利用nrm提供的终端命令,可以快速查看和切换下包镜像源
- 通过npm包管理工具,将nrm安装为全局可用的工具
- 查看所有可以用的镜像源 nrm ls
- 将下包的镜像源切换为淘宝镜像 nrm use taobao
6-4.包的分类
6-4-1.项目包(开发依赖包和核心依赖包)
- 被安装到项目的node_modules 目录中的包都是项目包
- 开发依赖包(被记录到devDependencies节点中的包,只在开发期间会用到) npm i 包名 -D
- 核心依赖包(被记录到dependencies节点中的包,在开发期间和项目上线后都会用到)npm i 包名
6-4-2.全局包
- 在执行npm install 命令时,如果提供了**-g** 参数,则会把包安装为全局包
6-4-3.规范的包结构
- 包必须以单独的目录而存在
- 包的顶级目录下必须要包含package.json这个包管理配置文件
- package.json中必须包含name、version、main这三个属性,分别代表包的名字、版本号、包的入口
6-5.创建属于自己的包
6-5-1.初始化包结构
- 新建一个liuqiang-tools文件夹,作为包的根目录
- 在根目录下有三个文件
- package.json(包管理配置文件)
- liuqiang-tools.js(包的入口文件)
- README.md(包的说明文档)
6-5-2.需要实现的功能
- 格式化日期
// 1. 格式化日期
// 初始化时间
function initTime(dateStr) {
const date = new Date(dateStr);
// 年月日
const y = date.getFullYear();
const m = padZero(date.getMonth() + 1);
const d = padZero(date.getDate());
// 时分秒
const h = padZero(date.getHours());
const mi = padZero(date.getMinutes());
const s = padZero(date.getSeconds());
return `${y}-${m}-${d} ${h}:${mi}:${s}`
}
// 定义补零函数
function padZero(n) {
return n > 9 ? n : '0' + n;
}
- 转义HTML中的特殊字符
// 2. 转义HTML中的特殊字符
function htmlTrans(htmlStr){
return htmlStr.replace(/<|>|"|&/g,(lable)=>{
switch(lable){
case '<':return '<'
case '>':return '>'
case '"':return '"'
case '&':return '&amt'
}
})
}
- 还原HTML中的特殊字符
// 3. 还原HTML中的特殊字符
function htmlUntrans(htmlStr){
return htmlStr.replace(/<|>|"|&amt/g,(lable)=>{
switch(lable){
case '<':return '>'
case '>':return '<'
case '"':return '"'
case '&amt':return '&'
}
})
}
module.exports = {
initTime,
htmlTrans,
htmlUntrans
}
6-5-3.测试运行(test.js)
代码演示:
const liuqiangTools = require('./liuqiang-tools')
var dt = new Date()
var str = "<h1>liu</h1>";
var str1 = ">h1<liu>/h1<";
console.log(liuqiangTools.initTime(dt));
console.log(liuqiangTools.htmlTrans(str));
console.log(liuqiangTools.htmlUntrans(str1));
结果展示:
6-5-4.模块化拆分
- 将格式化时间的功能,拆分到src中的initTime.js中
- 将处理HTML的功能,拆分到src中的htmlTrans.js中
- 在liuqiang-tools.js中导入另外两个模块,得到需要向外共享的方法
- 在liuqiang-tools.js中,使用module.exports把对应的方法共享出去
结果展示:
6-6.发布包
6-6-1.注册npm账号
- 访问http://www.npmjs.com/点击sign up注册
6-6-2.登录npm账号
- 在终端执行npm login 命令,依次输入用户名、密码、邮箱后就登陆成功了
- 登录之前一定要把下包的服务器换成npm的官方服务器
6-6-3.发布包
- 将终端切换到包的根目录之后,运行npm publish 命令,就可以把包发布到npm上
6-6-4.删除已经发布的包
- npm unpublish 包名 --force 从npm删除已经发布的包
- npm unpublish只能删除72小时以内发布的包,在24小时以内不允许重复发布
7.模块的加载机制
7-1.优先从缓存中加载
- 不论是内置模块、还是自定义模块、还是第三方模块,他们都会优先从缓存中加载,从而提高模块的加载效率
7-2.内置模块的加载机制
- 内置模块是由node.js官方提供的模块,内置模块的加载优先级最高
7-3.自定义模块的加载机制
- 使用require()加载自定义模块的时候,必须以 ./ 或**…/开头的路径标识符**
- 如果没有路径标识符,则node会把它当作第三方模块进行加载
- 同时,在require()导入自定义模块的时,如果省略了文件的扩展名,则node会安顺序加载以下文件
- 按照确切的文件名加载
- 补全.js扩展名加载
- 补全.json扩展名加载
- 补全.node扩展名加载
- 加载失败,报错
7-4.第三方模块的加载机制
- 如果传递给require()的模块时第三方模块,则node会从当前模块的父目录开始,尝试从/node——modules文件夹中加载第三方模块
- 如果没有找到,则移动上一层父目录中进行加载,知道文件系统的根目录
7-5.目录作为模块
- 当把目录作为模块标识符,传递给require(进行加载的时候,有三种加载方式:
- 在被加载的目录下查找一个叫做package.json的文件,寻找main属性,作为require()加载的入口
- 如果目录里没有package.json文件,或者main入口不存在或无法解析,则Node.js将会试图加载目录下的index.js文件。
- 如果以上两步都失败了,则Node.js会在终端打印错误消息,报告模块的缺失: Error: Cannot find module xxx’
8.express
请看Node.JS(中)