慕课网 前端面试加分福音--node基础 笔记
写在前面
- Node.js
- API部分 √
- 前端部分 ×
课程期望
- 了解Node是什么以及应用场景
- Node的基础知识
- 了解Node的核心模块
- 了解数据通信过程
- 自己实现登录、注册等功能
- 前后台的工作流程
这是课程的零碎笔记,包括但不限于案例实现。
Node.js介绍
Node介绍
Node的优势
优势:
- 性能高
- 便于前端入手
作用:
- 写webAPI
- 中间层:服务器中负责IO读写的中间层服务器
性能 异步IO 处理数据 安全性 - 前端工程化的一些工具都是基于node(webpack、gulp)
Node的环境搭建和运行
- 官网下载 node-v-xx.msi 安装包 安装
- node -v 检测是否安装成功,成功会显示安装版本
- 运行程序 在程序所在文件夹打开的命令行里 node xxx.js
Node包管理工具 npm
-
npm init
初始化
生成package.json
在需要的文件夹内shift+右键
打开命令行 -
cnpm
国内npm镜像的客户端
国内安装-g
是全局安装的意思npm install cnpm -g --registry=https://registry.npm.taobao.org
-
npm 常用命令
-
npm install xx
安装命令 可简写为npm i xx
-
npm uninstall xx
删除命令 可简写为npm un xx
-
npm update xx
更新某个包 -
npm i
把dependencies
中的依赖都装一遍
-
Node的模块
全局模块
定义:何时何地都能访问,不需要引用
process.env
环境变量console.log(process.env);//打印所有的 环境变量 console.log(process.env.path);//打印环境变量path
process.argv
打印命令 返回一个数组//输入命令node test执行test.js console.log(process.argv); PS D:\VSCODE\node> node test node -v [ 'D:\\Program Files\\nodejs\\node.exe', 'D:\\VSCODE\\node\\test', 'node', '-v' ] let th = process.argv[3]; console.log(th);//结果为-v
系统模块
定义:需要require(),但不需要单独下载
-
path模块:用于处理文件路径和目录路径的实用工具
let path = require('path')
path中有几个方法:
console.log(path.dirname('node/a/b/c/1.jpg'); //打印结果为/node/a/b/c console.log(path.basename('node/a/b/c/1.jpg'); //打印结果为1.jpg console.log(path.extname('node/a/b/c/1.jpg'); //打印结果为.jpg
可以通过这几个方法判断前端上传文件的类型
console.log(path.resolve('/node/a/b/c' ,'../../','d')); //打印结果为node\a\d,返回上两级的结果中的d console.log(path.resolve(_dirname ,'xx.js')); //可以打印出这个文件的绝对路径
-
fs模块:用于文件读写操作
let fs = require('fs')
fs中的方法:
异步
fs.readFile('./a.text',(err,data)=>{ if(err){ console.log(err);//打印错误信息 }else{ console.log(data.toString());//打印文件内容,不加tostring是二进制表示方式 } }) fs.writeFile('./b.text','写入内容',{flag:"a"}(err)=>{ //如果不加 {flag:"a"},写入内容会覆盖前一次的,a即append if(err){ throw err } }
同步
let data = fs.readFileSync('./a.text') conlise.log(data.toString()); fs.writeFileSync('b.text','写入内容')
自定义模块
定义 :require自己封装的模块
-
exports
-
module
-
require
- 新建一个模块,mod.js
exports.a=1;//向exports中塞一个a,暴露出去 let c = 3; //c是模块中的,没有暴露出去外面是拿不到的
- 新建一个index.js
//引进模块mod再赋给变量 const mod1 = require('./mod');// ./是指当前文件夹下 要引用当前文件夹下的mod.js .js可以省略 console.log(mod1.a);//结果为1 console.log(mod1.c);//结果为undefined
-
require 特性
- 如果有路径,就去路径中找
- 如果没有路径,就去node_modules中找
- 上面都没有,再去node的安装目录中找
//mod.js中 module.exports={a:1,b:2}//导出一个对象 //index.js中 const mod1 = require('./mod') console.log(mod1.a);//结果为1 console.log(mod1.b);//结果为2 module.exports=function(){ //导出一个function console.log('123'); } mod1();//结果为123 module.exports=class{ //导出一个class constructor(name){ this.name = name; } show(){ console.log(this.name); } } let p = new mod1('lily');//实例化 p.show();//结果为lily
重点:HTTP模块
-
服务器对象
http.createServer() //可以帮我们快速的搭建一个服务器
-
新建一个index.js
let http = require('http'); http.createServer((req,res)=>{ //console.log('连接成功'); //返回访问的目录 req.url //localhost:8080返回/ 就是根目录 //localhost:8080/index.html 返回 index.html res.write('index'); res.end(); //这样就结束了,访问的时候返回index //也可以简写 res.end('index1') 结果index1 }).listen(8080)//监听这个端口,相当于去一栋楼里找人的门牌号,然后去浏览器访问这个端口,上面的信息就可以被打印出来了
-
新建一个index.html,要把这个页面展示出来,用fs读取这个文件再展示
let http = require('http'); let fs = require('fs');//引入文件读写模块 http.createServer((req,res)=>{ fs.readFile(`./${req.url}`,(err,data)=>{ if(err){ res.writeHead(404); res.end('404 not found ') }else{ res.end(data) } }) }).listen(8080)
Node中的数据交互
- 数据报文分为:
请求头:信息 url <32k
请求体:数据 <2G
GET请求
-
主要是获取数据,数据是放在URL里进行传输,容量小<32k
-
结合创建服务器,拿到get请求中的数据
let http require('http') //req就是请求发过来的东西 //req.url发送请求过来的链接地址 //发送数据要用表单或者ajax //创建一个表单的html,用户名,密码 //action是指把数据提交到哪儿,后端的接口地址 <form action="http://localhost:8888/aaa" method="GET"> 用户名:<input> type="text" name="username"> 密码:<input> type="password" name="password"> <input> type="submit" value="提交"> </form> http.createServer((req,res)=>{ console.log(req.url); }).listen(8888)
-
启动服务 在表单输入用户密码 服务端得到结果
/** /aaa?username=asdfas&password=123123 */
-
中间就是传过来的信息,要得到其中的数据,引入URL模块
let url =require('url'); http.createServer((req,res)=>{ //url.parse() 解析,两个参数,加上true会自动返回query经过处理的结果 console.log(url.parse(req.url)); let { pathname, query } = url.parse(req.url, true); console.log(pathname, query); console.log(query.username); //结果 /**--------------------**/ Url { protocol: null, slashes: null, auth: null, host: null, port: null, hostname: null, hash: null, search: '?username=star&password=121', query: 'username=star&password=121', pathname: '/aaa', path: '/aaa?username=star&password=121', href: '/aaa?username=star&password=121' } //加上true参数之后 //query: [Object: null prototype] { username: 'star', password: '121' } /aaa [Object: null prototype] { username: 'star', password: '121' } star /**--------------------**/ }).listen(8888)
POST请求
-
数据是放在body里传输,容量大:<2G
数据量大 分段传输 就是多次执行
data
-
req.on()
方法
req.on('data',()=>{})
和req.on('end',()=>{})
on中有个回调函数是拿到的数据
data
一般是文件图片之类的 数据不能是字符串
计算机发送文件视频是以二进制的形式,所以使用这个buffer
-
end
表示结束 把数据放到数组里等拿完了一次性展示let http = require('http'); http.createServer((req,res)=>{ let reuslt = []; req.on('data',buffer=>{ result.push(buffer);//数据分段执行多次 /** console.log(buffer); //表单测试需将方法改为POST //用户名:aaa,密码:111 //返回结果:<Buffer 75 73 65 72 6e 61 6d 65 3d 61 61 61 26 70 61 73 73 77 6f 72 64 3d 31 31 31>*/ }) req.on('end',()=>{ //buffer 对象中的一个方法将结果拼起来 //返回结果<Buffer 75 73 65 72 6e 61 6d 65 3d 61 61 61 26 70 61 73 73 77 6f 72 64 3d 31 31 31> //tostring转换,但是对文件和图片不行,需要使用模块处理post请求 let data = Buffer.concat(result); console.log(data); /**console.log(result); //返回结果多了数组 [ <Buffer 75 73 65 72 6e 61 6d 65 3d 61 61 61 26 70 61 73 73 77 6f 72 64 3d 31 31 31> ] }) */ }).listen(8888)
案例
接口(API)
-
API:不同功能层之间的通信规则称为接口。
前端不能通过JS
直接操作数据库,接口帮着做这些事情 -
参数:前端告诉接口,查询什么,什么就是参数,拿到这个参数再去查数据库
-
返回值:拿到数据之后再返回给前端,叫做返回值
接口名:’/login’
请求方法:get
参数:username,password
返回值:JSON对象{ //错误信息 err:1, msg:"密码错误" }
接口名:’/regist’
请求方法:post
参数:username,password phonenum email
返回值:JSON对象{ //错误信息 err:1, msg:"注册失败" }
-
接口文档
项目:实现登录和注册
写代码之前的准备工作
- mkdir 文件夹名 ,新建项目文件夹;
- cd 文件夹名 ,进到这个文件夹中;
- npm init -y ,初始化 ;
- npm i nodemon -D,监听更新,服务自动启动,不用手动一遍遍启动;
- code ./,在vscode中打开代码。
正式开始
-
项目下新建src文件夹
-
src中新建app.js,引入http模块,搭建服务器
const http= require('http'); http.createServer((req,res)=>{ }).listen(8080, () => { console.log('服务启动成功'); })
-
在package.json中配置启动脚本
"scripts": { "start": "nodemon ./src/app.js" }
-
启动项目使用命令
npm (run) start
因为start
是默认的,可以加run
也可以不加,但是别的名称不能省略。 -
问题记录:使用npm start报错
nodemon
既不是内部命令也不是外部命令; -
解决:看package.json的依赖中有没有引进
nodemon
,如果没有可以使用命令npm install --save-dev nodemon
-
-
API需求分析
-
登录功能用
GET
请求; 注册功能用POST
请求。 -
首先是获取数据: 引入
url
模块,获取url
中传的username
和password
-
问题记录:- 视频中使用的是url.parse()方法,实际运行代码时出不来结果;
-
解决: 在nodejs 11.0以后的版本上使用,编译器会提示已过期(since v11.0.0 - Use the WHATWG URL
API),并推荐你使用URL
使用URL类对url进行操作,详细见官方文档const http= require('http'); const url = require('url'); const querystring = require('querystring'); http.createServer((req,res)=>{ //获取数据 let path,getmyurl,post if (req.method == 'GET') { /* url 模块中的url.parse方法已经被废弃了*/ //let { pathname, query } = url.parse(req.url, true) getmyurl = new URL('http://localhost:8080' + req.url); path = getmyurl.pathname //console.log('http://localhost:8080'+req.url); //console.log(path); //console.log(getmyurl.searchParams.get('username')); complete();//成功则调用函数 }else if (req.method == 'POST') { let arr = []; path = req.url console.log(path); req.on('data', buffer => { arr.push(buffer); }) req.on('end', () => { post = querystring.parse(Buffer.concat(arr).toString());//最后处理为json格式 如果有文件,这里不能直接使用toString complete() }) } function complete () {} }).listen(8080, () => { console.log('服务启动成功'); })
-
根据客户端传递过来的不同的参数(用户名/密码) 查询是否存在,并且实现登录;
-
实现 新增的一个用户 (用户名/密码)。
-
要点记录:在使用
fs
模块之前先引入;const fs = require('fs')
接下来是
complete ()
方法的实现function complete () { if (path == '/login') { res.writeHead(200, { "Content-Type":"text/plain;charset=utf-8" }) let username = getmyurl.searchParams.get('username') let password = getmyurl.searchParams.get('password');//接下来应该是判断数据库里有没有 //使用let user = { admin:123456 }代替,写在http.createServer之外 if (!user[username]) { res.end(JSON.stringify({ err: 1, msg:"用户名不存在" })) } else if (user[username] != password) { res.end(JSON.stringify({ err: 1, msg:"密码错误" })) } else { res.end(JSON.stringify({ err: 0, msg:"登录成功" })) } } else if (path == '/regist') { res.writeHead(200, { "Content-Type":"text/plain;charset=utf-8" }) let {username,password} = post if (user[username]) { res.end(JSON.stringify({ err: 1, msg:"用户已存在" })) } else { user[username] = password //注册 res.end(JSON.stringify({ err: 0, msg:"注册成功" })) } } else { //fs模块需要在前面引入 fs.readFile(`src${path}`, (err,data)=>{//读取页面文件src/login.html if (err) { res.end('404') } else { res.end(data) } }) } }
-
-
页面实现
-
要点记录:在使用
ajax
之前先引入jQuery
,可以使用命令行安装npm i jQuery
-
安装成功之后,在
node_modules
文件夹下的dist中就可以看到装好的jquey
,再在页面中进行引用即可<script src="./static/jquery.min.js"></script>
-
这里的是完善实现的部分代码:
用户名:<input type="text" id="username"><br> 密 码:<input type="password" id="password"><br> <button id="login">登录</button><br> <button id="regist">注册</button> <script> $('#login').click(function(){ $.ajax({ url:"/login", data:{ username:$('#username').val(), password:$('#password').val() }, dataType:"json", success(res){ if(res.err){ alert(res.msg) }else{ alert("登录成功!") location.href="admin.html"//后台页面 } } }) }) $('#regist').click(function(){ $.ajax({ url:"/regist", method:"post", data:{ username:$('#username').val(), password:$('#password').val() }, dataType:"json", success(res){ if(res.err){ alert(res.msg) }else{ alert("注册成功!") } } }) }) </script>
-
写在最后
简单的实现了登录与注册,没有使用到数据库,后续学习可以加上。