1、基础知识node.js
(1)JS解析引擎
让代码可以被执行。不同的浏览器使用不同的解析引擎。
让代码可以被执行。不同的浏览器使用不同的解析引擎。
chrome ------V8,性能好。
firefox ------odinMonkey
srfri----jscore
IE------chakra
(2)API常用的
DOM/BOM/ajax,等待执行的JS代码,调用WEB API,给JS解析引擎。
(2)API常用的
DOM/BOM/ajax,等待执行的JS代码,调用WEB API,给JS解析引擎。
运行环境,代码正常运行所需要的必要环境。chrome浏览器运行环境,V8解析引擎,内置API函数。
V8引擎负责解析执行代码,内置API是运行环境的特殊接口,浏览器提供的,只能在所属的运行环境中调用。
JS是否可以做后端开发?后端开发一般用JAVA/PYTHON/PHP。JS也可以做后端开发,但是要借助node.js实现。node.js是后端的一个运行环境。
(3)什么是node.js
在白龙网看来,是一个基于V8引擎的JS运行环境。如果JS代码放在浏览器,则是做前端开发,如果把JS代码放到node.js运行环境,则是做后端开发。
node.js的运行环境,包括V8引擎和内容API(fs/path/http/JS内置对象/querystring等),API提交给V8解析引擎。
浏览器是JS的前端运行环境;Node.js是JS的后端运行环境;node.js中无法调用DOM/BOM/AJAX等等浏览器内容API。
(4)Node.js能做什么?
提供了基础功能与API,
express框架----->构建WEB应用
electron框架----->构建跨平台的桌面应用
restfy框架------>构建API接口
读写操作数据库,创建实用的命令行工具辅助前端开发……
JS学习路径:
基础语法->浏览器内置API->第三方库(jq/atr-template);
node.js学习路径:
JS基础语法-》node.js内置API-》第三方模块。
(5)node.js安装
LTS版本:长期稳定版本,推荐安装;
current版本:新特性尝鲜,热衷于新特性的用户可以使用。
打开命令窗口/终端(Terminal),输入node -v 查看node.js版本号,说明安装成功。
(6)在node.js环境是执行JS代码
win+R,打开cmd终端,使用命令cd切换到js文件所在的路径,然后输入node js文件名,即可执行JS命令。
或者在js文件所在目录,按住shift+右键,打开powershell窗口,直接输入node js名称,即可执行JS代码。
(7)终端快捷键
方向键上,快速定位上一个命令;
tab键,快速补全输入命令;
esc,快速清空当前输入的命令;
cls,清空当前终端内容;
2、fs文件系统模块
文件系统模块,操作谁的的模块,提供了方法和属性,满足用户对文件 的操作需要。如果要在JS中使用FS操作文件,则需要先使用命令require('fs')导入它。
(1)fs.readFile() 读取文件指定的内容
①语法格式与使用步骤
A.新建一个测试文本文件1.txt并输入任意内容
B.新建一个JS文件1.js并输入如下代码
//1.导入fs
const fs = require('fs')
//2.读取文件
// 2-1第一参数是个字符串,指明被操作文件的路径
// 2-2第二个参数是编码格式,一般为utf8
// 2-3第三个参数是回调函数,带两个形参:读取失败、读取成功
fs.readFile('./11.txt','utf8',function(err,dataStr) {
console.log(err);
console.log('-----------');
console.log(dataStr);
// 3.读取结果
// 3-1如果读取成功,err的值为null,dataStr正常输出
// 3-2如果读取失败,err值为错误对象,dataStr的值为undefined
} )
C.打开powershell终端运行node 1.js
②利用回调函数形参返回结果判断文件是否读取成功
const fs = require('fs')
fs.readFile('./1.txt','utf8',function(err,dataStr) {
//1.如果err=true,高读取文件失败并给出提示
if(err) {
return console.log('文件读取失败' + err.message);
}
//2.如果err=null,则读取文件成功并打印
console.log('文件读取成功' + dataStr);
} )
(2)fs.writeFile() 向指定的文件中写入内容
①语法格式
//1.导入文件系统
const fs = require('fs')
//2.调用fs.write()
// 2-1第一个参数是字符串,声明写入的文件路径;如果本地有2.txt,则直接写入,如果没有写入的文件,则自动创建该文件后再写入
// 2-2第二个参数是要写入的数据
// 2-3第三个参数,是数据的编码格式,默认utf8,可以写,也可以省略
// 2-4第四个参数,是回调函数,带一个形参
fs.writeFile('./2.txt','白龙网','utf8',function(err) {
// 3.写入成功,则err的值为null,写入失败,则err的值为错误对象
console.log(err);
})
②判断写入是否成功
const { log } = require('console');
const fs = require('fs')
fs.writeFile('./2.txt','白龙网','utf8',function(err) {
console.log(err);
if(err) {
return console.log('写入失败' + err.message);
}
console.log('文件写入成功');
})
案例1:考试成绩管理
//1.导入文件系统
const { log } = require('console')
const fs = require('fs')
//2.调用读取方法
fs.readFile('./成绩.txt','utf8',function(err,dataStr) {
//3.判断读取数据是否成功
if(err) {
return console.log('读取文件失败:' + err.message);
}
console.log('文件读取成功' + dataStr);
// 4-1把字符串分割成数组1,用空格隔开
const arrOld = dataStr.split(' ')
console.log(arrOld);
// 4-2遍历数组,并替换等号,把修改后的内容放入新数组2
const arrNew = [];
arrOld.forEach(item => {
const str = item.replace('=',':');
arrNew.push(str);
})
console.log(arrNew);
// 4-3把数组2拼接成字符串
const newStr = arrNew.join('\r\n');
console.log(newStr);
//5.fs.readFile()把处理好的数据写入新文件
fs.writeFile('./ok.txt',newStr,function(err){
if(err) {
return console.log('成绩写入失败' + err.message);
}
console.log('成绩写入成功\n' + newStr);
})
})
③路径动态拼接问题
在使用fs模块操作文件时,如果提供的操作以./ ../开发的相对路径时,很容易出现路径动态拼接错误的问题。
原因是,代码在运行的时候,会以执行node命令时所处的目录,动态的拼接出被操作文件的完整路径。
如果要解决这个问题,可以在读写文件时,提供绝对路径即可。这个问题解决了路径拼接的问题,但是可移植性差,并且在JS中一个\表示转义,两个\\才表示\,如下:
C:\\Users\\bailong\\Desktop\\node\\ok.txt
终极解决办法是,使用__dirname(当前目录)再拼接相对路径,即可实现动态路径正确拼接的问题:
const fs = require('fs')
//1.使用__dirname动态拼接路径
fs.readFile(__dirname + '/成绩.txt','utf8',function(err,dataStr) {
if(err) {
return console.log('读取文件失败:' + err.message);
}
console.log('文件读取成功' + dataStr);
const arrOld = dataStr.split(' ')
console.log(arrOld);
const arrNew = [];
arrOld.forEach(item => {
const str = item.replace('=',':');
arrNew.push(str);
})
console.log(arrNew);
const newStr = arrNew.join('\r\n');
console.log(newStr);
//2.使用__dirname动态拼接路径
fs.writeFile(__dirname + '/ok.txt',newStr,function(err){
if(err) {
return console.log('成绩写入失败' + err.message);
}
console.log('成绩写入成功\n' + newStr);
})
})
3、path路径模块
处理路径的模块,满足用户对路径的处理需求。在使用下述方法之前,要先导入路径模块:const path = require('path')
(1)path.join()把多个路径片段拼接成一个完整的路径字符串
凡是涉及路径拼接,都可以使用paht.join()方法来实现。
const { log } = require('console');
const path = require('path');
const fs = require('fs');
//../会抵消一级目录
const pathStr = path.join('/a','/b/c','../','/d','/e');
console.log(pathStr);
//用path.join()拼接fs.readFile()方法第一个路径参数
fs.readFile(path.join(__dirname,'./ok.txt'),'utf-8',function(err,dataStr) {
if(err) {
return console.log('读取失败' + err.message);
}
console.log(dataStr);
})
(2)paht.basename()从路径字符串中,把文件名解析出来
这个方法可以获取路径的最后一部分,通过用这个方法获取路径中的文件名。
const path = require('path');
const fpath = 'a/b/c/d/index.html';
//获取完整的文件名
const fullName = path.basename(fpath);
console.log(fullName);
//返回index,第二参数是文件的扩展名,如果存在,会删除文件的扩展名,只返回文件名
const fullName2 = path.basename(fpath,'.html');
console.log(fullName2);
//获取文件的扩展名
const fext = path.extname(fullName);
console.log(fext);
案例1:时钟案例
把一个含有HTML、JS、CSS方文档拆分为三个文件:index.html、index.js、index.css
//导入文件模块
const fs = require('fs')
//导入路径模块
const path = require('path')
//定义正则表达式,匹配所有CSS/JS
const regStyle = /<style>[\s\S]*<\/style>/;
const regJs = /<script>[\s\S]*<\/script>/;
//读取文件内容
fs.readFile(path.join(__dirname,'./index.html'),'utf-8',function(err,dataStr) {
if(err) {
return console.log('读取html失败' + err.message);
}
// console.log(dataStr);a
//调用3个函数,分别提取html/css/js
resolveCss(dataStr);
resolveJs(dataStr);
resolveHtml(dataStr);
})
//CSS处理函数
function resolveCss(htmlCss) {
//使用正则表达式选取样式
const r1 = regStyle.exec(htmlCss)
//替换样式的开始、结束标识
const newCss = r1[0].replace('<style>','').replace('</style>','')
//把样式写稿css.css文件
fs.writeFile(path.join(__dirname,'/clock/css.css'),newCss,'utf-8',function(err) {
if(err) {
return console.log('写入CSS失败' + err.message);
}
console.log('样式成功定稿css.css文件');
})
}
//JS处理函数
function resolveJs(htmlStr) {
const r2 = regJs.exec(htmlStr);
// console.log(r2);
const newJs = r2[0].replace('<script>','').replace('</script>','')
fs.writeFile(path.join(__dirname,'./clock/js.js'),newJs,'utf-8',function(err) {
if(err) {
return console.log('JS写入失败' + err.message);
}
console.log('JS数据写入成功');
})
}
//html处理函数
function resolveHtml(htmlStr) {
//把内联样式、JS转换为外联样式、JS
const newHtml = htmlStr.replace(regStyle,'<link rel="stylesheet" href="./css.css">').replace(regJs,'<script src="./js.js"></script>');
fs.writeFile(path.join(__dirname,'./clock/index.html'),newHtml,'utf-8',function(err) {
if(err) {
return console.log('写入HTML失败' + err.message);
}
console.log('HTML成功写入');
})
}
注意:
fs.writeFile()只能用来创建文件,不能创建目录;
重复调用fs.writeFile(),新内容会覆盖旧内容,不会报错;
4、http模块
(1)http模块概念与作用
消费资源的电脑叫客户端;提供资源的电脑叫服务器。
创建WEB服务器模块,通过HTTP模块提供的http.createServer()方法,就能把一台变成一台WEB服务器,对外提供WEB服务。同时,在使用http模块之前,要先导入:const http = reuqire('http)
服务器与普通电脑的区别,在于是否安装了服务器软件,如IIS/APACHE/ PHPSTUDY等。
node.js不需要使用第三方服务器软件,可以通过http模块,通过几行简单的代码就能的手写一个服务器软件,从而对外提供WEB服务器软件。
(2)服务器相关概念
IP地址,每台服务器都有自己的IP地址。
域名,IP地址的别名,
IP与域名是一一对应的关系,IP与域名对应关系的服务器是域名服务器DNS。
127.0.0.1 localhost
端口号,如同门牌号,每个WEB服务对应一个端口号。URL中的80端口可以被省略,只有80端口可以省略。apache默认端口号是80。
(3)创建基本的web服务器
①方法:
导入http模块;const http = require('http)
创建web服务器实例;const server = http.createServer()
为服务器实例绑定request事件,监听客户端请求;server.on('request',function(req,res) {})
启动服务器:server.listen(80,()=>{})
在vscode“终端->新建终端”新建一个终端用来运行JS。
const http = require('http');
const server = http.createServer();
server.on('request',function(req,res) {
console.log('welcome visit web server');
});
server.listen(8080,function() {
console.log(('server running at 127.0.0.1'));
})
②req请求对象
只要服务器接收了客户端的请求,就会调用通过server.on()为服务器绑定的request事件处理函数。如果想在事件处理函数中,访问与客户端相关的数据或者属性,可以使用req.url,req.method等。
const http = require('http');
const server = http.createServer();
server.on('request',(req) => {
const url = req.url;
const method = req.method;
const str = 'url=' + url + '\n' + 'method=' + method;
console.log(str);
})
server.listen(80,() => {
console.log('server running at http://localhost');
})
③res响应对象
res.end()用来响应内容,结束请求过程。
const http = require('http');
const server = http.createServer();
server.on('request',(req,res) => {
const url = req.url;
const method = req.method;
const str = 'url=' + url + '\n' + 'method=' + method;
// 响应用户请求的数据
res.end(str)
})
server.listen(80,() => {
console.log('server running at http://localhost');
})
④解决中文乱码
const http = require('http');
const server = http.createServer();
server.on('request',(req,res) => {
const url = req.url;
const method = req.method;
const str = '你请求的网址是:' + url + '\n' + '你请求的类型是:' + method;
//如果出现乱码,可以指定编辑格式为utf-8
res.setHeader('content-type','text/html;charset=utf-8');
// 响应用户请求的数据
res.end(str)
})
server.listen(80,() => {
console.log('server running at http://localhost');
})
⑤根据不同url响应不同的页面
const http = require('http');
const server = http.createServer();
server.on('request',(req,res) => {
//1.获取URL
const url = req.url;
//2.定义一个变量
let content = '404 Not found';
//3.判断首页内容显示
if(url === '/' || url === '/index.html') {
content = '<h1>首页</h1>';
//4.判断列表页内容显示
} else if (url === '/about.html') {
content = '<h1>关于我们</h1>'
}
//5.防止乱码
res.setHeader('content-type','text/html;charset=utf-8');
//6.响应给用户的数据
res.end(content);
});
server.listen(8088,() => {
console.log('server is running at http://127.0.0.1');
})
⑥时钟web服务器的搭建
这个服务器的搭建重点是获取到相对路径后,把它拼接成完整的绝对路径;然后根据网站首页,列表页,分别从后台拼接出对应的页面路径。
//1、导入模块
const http = require('http');
const fs = require('fs');
const path = require('path');
//2、创建服务器
const server = http.createServer()
//3、监听服务器事件
server.on('request',(req,res) => {
//3-1获取文件的url
const url = req.url;
console.log('123');
//3-2把请求的url映射为具体的文件存放路径,判断如果是首页,就从后端拼接一个/clock的目录,如果是其它目录,就增加一级目录
// const fpath = path.join(__dirname,url);
let fpath = '';
if(url === '/') {
fpath = path.join(__dirname,'./clock/index.html');
}else {
fpath = path.join(__dirname,'./clock',url);
}
//读取文件并响应给客户端
fs.readFile(fpath,'utf-8',(err,dataStr) => {
if(err) {
return res.end('404 Not found');
}
res.end(dataStr);
})
})
//4、启动服务器
server.listen(80,() => {
console.log('server running at http://127.0.0.1');
})