Nodejs 从入门到进阶
9:25
2020/4/26
3年前的视频
以下是Node可以实现的工作:(仅作了解)
Web 服务器
命令行工具
网络爬虫
桌面应用程序开发(Electron)
app
嵌入式
游戏
交互模式(repl模式)仅作了解 cmd
三、Nvm的安装和初步使用
从上一节我们知道,NodeJS有太多的版本了,切记,并不是新版本一出现,旧的版本就不去用了。
在不同的项目开发过程中,可能需要我们在电脑中同时存在多个不同版本的Node。
这时候就需要一个软件,来更好地管理这些不同版本地Node存在我们地电脑中,Nvm就是这样一个软件nym(node.is version manager的简写)翻译过来nodeis版本管理器.
3.1、安装Nvm
nvm下载链接 https://github.com/coreybutler/nvm-windows/releases
nvm配置镜像
3.2、nvm命令
nvm version:查看 nvm 的版本
nvm list:查看当前安装的Node.js所有版本(常用)
nvm install 版本号[架构]:安装指定版本的 Node.js(常用)
nvm uninstall 版本号:卸载指定版本的 Node.js
nvm use 版本号:选择指定版本的 Node.js(常用)
安装最新版本
nvm install latest
讲课node版本 10.15.0
Code Runner vscode插件
五、Node的注意事项(了解)
1、nodejs:ECMAScript +核心的api(重点).没有DOM、BOM
ecma dom bom js 三大组成部分
2、nodejs提供了文件操作系统(fs),还提供了web服务的功能(http),即使用nodejs可以编写一个web服务器]
(这两点在这先知道即可,后面我们会详细讲到)
浏览器:javascript三个部分:ECMAScript + BOM + DOM
服务器:javascript = ECMAScript +系统内置的核心模块(fs http)
六、ES6语法的简介
浏览器:javascript三个部分:ECMAScript + BOM + DOM服务器:javascript = ECMAScript +系统内置的核心模块(fs http)
ECMAScript 是什么?
是一个规范。ECMA是一个组织协会,协会专门负责制定各种规则。他们制定了一个ECMAscript规范,规定脚本语言实现。变量声明 var function fnName有哪些语言实现这个规范:1.JavaScript 2.actionScript(flash 动画 flash小游戏)
发展过程中 js 有很多的版本的迭代
我们前面学习的版本 ECMAscript5 版本
现在学习 ECMAScript6版本,也叫做es6版本。引入了很多新的语法特性。例如使用 let 声明变量 const 声明常量。
七、var的弊端及let关键字
使用var关键字声明变量的弊端:
1、var声明的变量有预解析,造成 逻辑混乱,可以先使用,后声明
2、var可以重复定义同一个变量,逻辑错误,第二次应该是修改变量,而不是定义
3、var用在for循环条件中,造成for循环的污染的问题
4、var声明的变量没有块级作用域(ESS中的作用域:全局和局部)
作者 叩丁狼 blibli
八、用const定义常量
1、const用来定义常量,修改就会报错
2、我们约定俗成地把常量都命名为大写
3、对象型常量中的属性可以修改
4、数组型常量中的每一项数据的引用可以修改
十二、ES6其他注意事项
注意:es6 语法特性如果是在nodejs的高版本执行没啥问题,高版本支持 es6;如果是nodejs 低版本 45 不支持
es6(ECMAScript6 ECMAScript2015)除了可以在nodejs 也可以在浏览器执行注意:浏览器高版本才可以执行,如果是 IE 678 肯定不认识,直接报错。
需求:es6写起来很爽,很方便,浏览器并不能全部支持。如何解决呢?
使用 babel 翻译器
考拉less sass--考拉--css es6----babel---es5(基本所有的浏览器全部支持)
在线编译网址:
https://www.babeljs.cn/repl
全局对象 global
后面看到所有的全局变量,例如console,setTimeout和 process是 global 变量的成员。我们甚至可以向全局变量添加成员,使其在任何地方都可用。
交换模式 this===global true
test.js 文件里 this===gloabl false 当一个模块 函数运行
AMD 规范:Require.is
CMD 规范:Sea.js
Common/s 的 Modules 规范:Node.is
ES6 模块化规范
exports.num=num
module.exports={num,fn}
exports是module.exports的引用,文件中才有exports
交换模式 没有exports 有module.exports
文件下 this===exports true
常用的内置模块如下:
fs:文件操作
http:网络操作
path:路径操作
querystring:查询参数解析
url:url 解析
nodeis内置模块的文档网址:http://nodejs.cn/api/
console.log(__dirname)//得到当前执行的文件的绝对路径,不包括文件名
console.log(__filename)//得到当前执行的文件的绝对路径,包括文件名
const path=require("path")
let extname=path.extname(__filename)
path.extname获取文件的扩展名(后缀名)
basename获取文件名(包含后缀名)
dirname获取文件当前所在路径
path.parse把路径解析成一个对象(所在盘符,所在路径,文件名后缀名)
let fullpath=path.join(__dirname,'path.js')获取path.js这个文件的完整路径
let fullpath=path.join(__dirname,'js','path.js')
__dirname/js/path.js (一层目录就是一个参数)
console.log(process.argv)
//获取到执行文件的时候,命令行所有的参数,作为元素放在这个数组中。
process.arch 获取执行环境的系统位数
express koa2 egg
process对象(仅做了解)
console.log(globalThis)
041、buffer对象中数据转成字符串.mp4
五、Buffer数据类型
JavaScript语言自身只有字符串数据类型,没有二进制数据类型。但在处理像文件流时(文件读写操作),必须使用到二进制数据。因此在Node.js中,定义了一个Buffer类,该类用来创建一个专门存放二进制数据的缓存区。
说白了,Buffer类似于一个整数数组。
<Buffer 61 62 63> 16进制的
let buf=Buffer.from([97,98,99])
Buffer.from('nodejs')
console.log(buf)//<Buffer 61 62 63>
console.log(buf.toString())//abc
仅做了解:
let buf=Buffer.alloc(10)//创建一个可以存放10个字符的buffer对象
buf.write('abc')//往buffer对象里面写入信息,(转2进制再转16进制存起来)
console.log(buf.toString())
042、同步读取文件信息.mp4
Node.is 的API内置有两个模块:path 和fs,我们使用JavaScript代码编写程序运行在Node.is 环境中就可以操作文件
同步读取:读取文件的时候,要等到文件读取完毕,才会执行后面的代码(sync 同步)
异步读取:不用等到文件读取完毕,就会执行后面的代码
node-snippets 提示
const fs=require('fs')
const path=require('path')
let filePath=path.join(__dirname,'hello.txt')
// let buf=fs.readFileSync(filePath)
// console.log(buf.toString())
let buf=fs.readFileSync(filePath,'utf-8')
console.log(buf)
http://www.taodudu.cc/news/show-3649479.html?action=onClick
vscode node代码补齐
043、异步读取文件信息.mp4
fs.readFile(filePath,'utf-8')
errot是错误信息,如果读取没发生错误,就为null
data读取到的内容,当出现错误的时候data就是undefined
const fs=require('fs')
const path=require('path')
let filePath=path.join(__dirname,'hello.txt')
fs.readFile(filePath,'utf-8',(error,data)=>{
if(error){
console.log(error)
return
}
console.log(data)
})
044、异步写入文件信息.mp4
异步写入
fs.writeFile(文件路径文件名,写入的内容,"utf-8",回调函数)
const fs=require('fs')
const path=require('path')
let filePath=path.join(__dirname,'hello.txt')
fs.writeFile(filePath,'javascript is nodejs','utf-8',(error)=>{
if(error){
console.log(error)
return
}
console.log('write content success!!!')
})
045、批量修改文件名案例.mp4
fs.renameSync(旧文件名,新文件名)
let namelist=fs.readdirSync(__dirname)//获取当前目录下文件名数组
str.endsWith('.js') //判断是否与,js结尾
startWith
substring
const fs=require('fs')
let namelist=fs.readdirSync(__dirname)
namelist.forEach(item=>{
if(item.endsWith('.js')){
fs.renameSync(item,`[koo]${item}`)
}
})
046、批量删除文件名前缀的案例.mp4
const fs=require('fs')
let namelist=fs.readdirSync(__dirname)
let startStr='[koo]' //4
namelist.forEach(item=>{
if(item.endsWith('.js')){
fs.renameSync(item,item.substring(startStr.length))
}
})
45 55
049、回调地狱.mp4
050、IP地址和端口号.mp4
ip地址标识网络上不同的设备(可联网的设备)
端口号 标识同一台设备上的不同的网络进程
网络进程(可联网的,运行起来的程序)
051、http请求的大致过程_粗略讲解_.mp4
053、http模块的一些使用细节.mp4
responese.write
const http=require('http')
const port=8080;
//创建服务器对象
const server=http.createServer((request,response)=>{
//requset请求对象,response响应对象
//每接收到一次请求就来执行一次这里的代码
response.write('hello nodejs http write')//可以网浏览器书写一些响应体内容
response.end('hello nodejs http')//表示响应工作已经结束
// write 和end相同点,都可以传入参数表示往浏览器书写一定内容
// write 和end不同点,write可以连续操作,end表示响应结束一般放最后
})
//调用服务器对象的监听方法,让服务器监听浏览器的请求
server.listen(port,(error)=>{
console.log('WebServer is listening at port 8080!')
})
055、获取请求的一些信息.mp4
request.url
pm2
056、对post请求的处理.mp4
const express=require('express') //npm i express
const path=require('path')
const fs=require('fs')
const app=express();
//用户访问注册页面
app.get('/register',(req,res)=>{
//用户请求注册页面,我们在这里返回注册页面
//1、获取文件路径
let filePath=path.join(__dirname,'views','register.html')
//2、读取文件信息
let registerPage=fs.readFileSync(filePath,'utf-8')
//3、返回注册页面
res.send(registerPage)
})
app.get('/',(req,res)=>{
res.send('首页!')
})
app.post('/register',(req,res)=>{
//接收-post提交的请求
res.send('post ok!')
})
app.listen(3000,()=>{
console.log('服务器已经启动!3000端口')
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>注册页面</title>
</head>
<body>
<h1>注册页面</h1>
<hr>
<form action="/register" method="post" enctype="application/x-www-form-urlencoded">
<p>用户名: <input type="text" name="username" placeholder="请输入用户名"></p>
<p>邮箱: <input type="text" name="email" placeholder="请输入邮箱"></p>
<p>密码: <input type="text" name="password"></p>
<p>确认密码: <input type="text" name="cerpassword"></p>
<p><input type="submit"></p>
</form>
</body>
</html>
057、获取get请求参数.mp4
const url=require('url')
const server=http.creaateServer((request,response)=>{
request.method //获取请求方式
let reqUrl=request.url
let obj=url.parse(reqUrl,true)
console.log(obj.query)
response.end()
})
pm2 nodemon
058、在vscode中设置nodemon启动.mp4
npm install -g nodemon
run code 第一个设置setting.json
059、获取post请求参数.mp4
const server=http.creaateServer((request,response)=>{
request.on('data',(postData)=>{
console.log(postData.toString())
})
response.end()
})
060、搭建http服务器.mp4
const server=http.creaateServer((request,response)=>{
//如果需要解决中文乱码,需遵循http协议
//response.setHeader('Content-type','text/html;charset=utf-8')
//文件路径 读取文件 响应文件
let filepath=path.join(__dirname,'views','index.html')
let content=fs.readFileSync(filepath)
response.end(content)
})
061、根据不同的请求返回不同的资源.mp4
request.url判断
062、npm简介.mp4
065、yarn的安装和使用.mp4
官网:
https://yarnpkg.com/en/docs
中文参考链接:
https://yarn.bootcss.com/
npm install -g yarn
| npm | yarn |
|---|---|
| npm init -y | yarn init -y |
| npm install react --save | yarn add react |
| npm uninstall react --save | yarn remove react |
| npm install react --save-dev | yarb add react --dev |
| npm update --save | yarn upgrade |
| npm install -g @vue/cli | yarn global add @vue/cli |
066、nodejs中不支持es6模块化语法的解决方案.mp4
NODE引擎默认情况下不支持ES6的模块化规范
可以交给第三方的转换工具(babel-cli 和 browserify)实现
yarn global add babel-cli browserify 或者 npm install babel-cli browserify -g
在自己项目目录下执行:
yarn add babel-preset-es2015或者npm install babel-preset-es2015--save-dev
babel-cli转es5 browserify兼容性问题
4、在项目目录下书写完代码后,执行:
babel src-d lib
067、babel不是内外部命令的解决方式.mp4
069、的模块化规范.mp4
070、Promise简介.mp4
071、Promise的基本使用.mp4
072、then的链式调用.mp4
073、使用Promise实现之前读取文件_基础版_.mp4
074、使用Promise实现之前读取文件_函数版_.mp4
075、util版.mp4
const util = require('util');
let readFilePromise = util.promisify(fs.readFile);
077、promise对象的catch方法和finally方法.mp4
078、Promise的all方法.mp4
079、Promise的race方法.mp4
080、读写文件案例_async_await版_.mp4
081、async_await的注意事项.mp4
1.如果await后面只写一个基本数据类型,会这个基本数据类型进行包装,包装成一个 Promise 对象
1324
083、浏览器请求服务器的大致流程画图解析.mp4
二、浏览器访问网站的基本过程
1、基本流程
用户输入网址,
浏览器请求DNS服务器,获取域名对应的IP地址,
请求连接该IP地址服务器,
发送资源请求.(遵循HTTP协议)
web服务器接收到请求,并解析请求,判断用户意图,
获取用户想要的资源,(链接数据库从数据中获取数据)
将资源返回给http服务器程序,
http服务器程序将资源数据通过网络发送给浏览器(响应给浏览器)
浏览器解析呈现请求的数据
084、http协议简介.mp4
三、Http协议简介
HTTP协议就是超文本传输协议(HyperText Transfer Protocol),通俗理解是浏览器和web服务器传输数据格式的协议,HTTP协议是一个应用层协议。
HTTP协议是基于TCP协议的,发送数据之前需要建立好连接
HTTP是万维网的数据通信的基础。设计HTTP最初的目的是为了提供一种发布和接收HTML页面<网页>的方法。
HTTP协议的制作者是蒂姆·伯纳斯-李,他供职于CERN(欧洲核子研究组织)
1991年发布的0.9版,该版本极其简单,只有一个GET请求方法
1996年5月,HTTP/1.0版本发布
1997年1月,HTTP/1.1版本发布,目前使用就是HTTP/1.1版本
085、http请求报文的格式介绍.mp4
086、post请求的演示.mp4
网络调试助手
087、http响应报文格式介绍.mp4
088、谷歌浏览器开发者工具的使用.mp4
089、TCP模型_三次握手_了解_.mp4
七、TCP/IP模型 三次握手四次挥手(了解)
http协议是基于TCP/IP协议的,TCP/IP协议是一个可靠的传输协议。
浏览器(客户端)和服务器建立连接的时候,发生三次握手:
090、TCP模型_四次挥手_了解_.mp4
三次握手建立连接时
四次挥手断开连接时
091、OSI七层网络模型_了解_.mp4
八、osI七层模型(了解)
七层模型,亦称OSI(Open System Interconnection)。参考模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系,一般称为OSI参考模型或七层模型。
说白了,就是两台计算机之间进行通信的时候,经历了哪些工作。
092、ajax开篇介绍.mp4
094、ajax的介绍.mp4
优缺点:
优点:Web应用程序更为迅捷地回应用户动作,并避免了在网络上发送那些没有改变的信息,减轻服务器压力。
缺点:浏览器实现之间有差异处理兼容性问题;不能回退和前进;默认不支持跨域访问(https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy.)。
095、ajax的书写步骤和状态流程.mp4
096、复习http服务器代码.mp4
097、ajax的get请求.mp4
let ajax=new XMLHttpRequest()
ajax.open("GET",'/url')
ajax.onreadystatechange=()=>{
if(ajax.readyState===4&&ajax.status===200){
console.log(ajax.responseText)
div.innerHTML=ajax.responseText
}
}
ajax.send()
098、ajax的post请求前准备.mp4
兼容性问题
function createAjax(){
var ajax
try{
ajax=new XMLHttpRequest()
}
catch(e){
ajax=new ActiveXObject('Microsoft.XMLHTTP')
}
return ajax
}
100、ajax的发送post请求.mp4
let ajax=new XMLHttpRequest()
let params={
username,
password
}
ajax.open("POST",'/url')
ajax.onreadystatechange=()=>{
if(ajax.readyState===4&&ajax.status===200){
console.log(ajax.responseText)
div.innerHTML=ajax.responseText
}
}
ajax.send(JSON.stringify(params))
101、避免缓存问题和超时处理的问题.mp4
避免缓存问题的写法:
AJAX 能提高页面载入的速度主要的原因是通过 AJAX 减少了重复数据的载入,也就是说在载入数据的同时将数据缓存到内存中,一旦数据被加载其中,只要我们没有刷新页面,这些数据就会一直被缓存在内存中,当我们提交的URL与历史的URL一致时,就不需要提交给服务器,也就是不需要从服务器上面去获取数据,虽然这样降低了服务器的负载提高了用户的体验,但是我们不能获取最新的数据。为了保证我们读取的信息都是最新的,我们就需要禁止他的缓存功能。解决方式有以下几种:
在 URL 后面加上一个随机数:Math.random()。
在 URL 后面加上时间搓:new Date().getTime()。
在使用 AJAX 发送请求前加上 ajax.setRequestHeader('Cache-Control','no-cache')。
超时处理:
有时网络会出现问题或者服务端出问题导致请求时间过长,一般提示网络请求稍后重试,以增加用户的体验感。在代码中我们可以通过定时器和请求中断来实现超时处理的效果。
var timer=setTimeout(function(){
ajax.abort()//取消请求,中断请求
},5000)
102、ajax方法的抽取_了解_.mp4
103、jquery的ajax方法介绍.mp4
$.ajax()
$.ajax({
url:'/get_data',
type:'get',
data:{
name:'nodejs'
},
success:(resp)=>{
$('#div').html(resp)
}
})
$.get()
105、使用jquery进行ajax的post请求.mp4
107、Express框架简介.mp4
npm提供了大量的第三方模包,其中不乏许多Web框架,我们没有必要重复发明轮子,因而选择使用Express作为开发框架,因为它是目前最稳定、使用最广泛,而且 Node.js 官方推荐的唯--个Web开发框架。除了为http 模块提供了更高层的接口外,还实现了许多功能,其中包括:
静态文件服务;路由控制;模板解析支持;动态视图;用户会话;CSRF 保护;错误控制器访问日志;缓存;插件支持。
官网:http://www.expressjs.com.cn/
express 是一个基于内置核心 http 模块的,一个第三方的包,专注于 web 服务器 的构建。
koa egg
108、体验express_搭建ex服务器.mp4
const express=require('express')
const app=express()
app.get('/',(req,res)=>{
res.send('hello world')
})
app.listen(3000,()=>{
console.log('Server start')
})
109
const express=require('express')
const path=require('path')
const fs=require('fs')
const app=express()
app.get('/register',(req,res)=>{
let filePath=path.join(__dirname,'views','register.html')
let content=fs.readFileSync(filePath,'utf-8')
res.send(content)
})
app.get('/',(req,res)=>{
res.send('hello world')
})
app.listen(3000,()=>{
console.log('Server start')
})
110、获取get请求的参数.mp4
const express=require('express')
const app=express()
app.get('/index',(req,res)=>{
console.log(req.query) //获取字符串参数,是一个对象 http://127.0.0.1:3000/index?name=koo&age=28
res.send('heloworld')
})
app.listen(3000,()=>{
console.log('Server start,port 3000')
})
111、处理post请求的接口.mp4
app.post('/index',(req,res)=>{
})
112、获取post请求的参数.mp4
npm install body-parser
const express=require('express')
const path=require('path')
const fs=require('fs')
//1.引入
const bodyParser=require('body-parser')
const app=express()
//注册到app
app.use(bodyParser.urlencoded({extended:false})) //false接收的值为字符串或者数组,true则为任意类型
app.use(bodyParser.json()) //解析json格式
app.get('/register',(req,res)=>{
let filePath=path.join(__dirname,'views','register.html')
let content=fs.readFileSync(filePath,'utf-8')
res.send(content)
})
app.get('/',(req,res)=>{
res.send('hello world')
})
app.post('/register',(req,res)=>{
//3.获取参数
console.log(req.body)
res.send('post ok')
})
app.listen(3000,()=>{
console.log('Server start')
})
express ex拍s
114、重定向_redirect_.mp4
res.redirect('/login') //重定向到/login
const express=require('express')
const path=require('path')
const fs=require('fs')
//1.引入
const bodyParser=require('body-parser')
const app=express()
//注册到app
app.use(bodyParser.urlencoded({extended:false})) //false接收的值为字符串或者数组,true则为任意类型
app.use(bodyParser.json()) //解析json格式
app.get('/register',(req,res)=>{
let filePath=path.join(__dirname,'views','register.html')
let content=fs.readFileSync(filePath,'utf-8')
res.send(content)
})
app.get('/',(req,res)=>{
res.send('hello world')
})
app.get('/login',(req,res)=>{
let filePath=path.join(__dirname,'views','login.html')
let content=fs.readFileSync(filePath,'utf-8')
res.send(content)
})
app.post('/register',(req,res)=>{
//3.获取参数
console.log(req.body)
// res.send('post ok')
// res.writeHead(302) //修改状态码
// res.writeHead(304.{name:'nodejs'})
res.redirect('/login') //重定向到/login
})
app.listen(3000,()=>{
console.log('Server start')
})
115、用all方法来合并相同路径的请求.mp4
app.all post get合并相同路径的请求
const express=require('express')
const path=require('path')
const fs=require('fs')
//1.引入
const bodyParser=require('body-parser')
const app=express()
//注册到app
app.use(bodyParser.urlencoded({extended:false})) //false接收的值为字符串或者数组,true则为任意类型
app.use(bodyParser.json()) //解析json格式
app.all('/register',(req,res)=>{
if(req.method==='GET'){
let filePath=path.join(__dirname,'views','register.html')
let content=fs.readFileSync(filePath,'utf-8')
res.send(content)
}
else if(req.method==='POST'){
console.log(req.body)
res.redirect('/login')
}
})
// app.get('/register',(req,res)=>{
// let filePath=path.join(__dirname,'views','register.html')
// let content=fs.readFileSync(filePath,'utf-8')
// res.send(content)
// })
app.get('/',(req,res)=>{
res.send('hello world')
})
app.get('/login',(req,res)=>{
let filePath=path.join(__dirname,'views','login.html')
let content=fs.readFileSync(filePath,'utf-8')
res.send(content)
})
// app.post('/register',(req,res)=>{
// //3.获取参数
// console.log(req.body)
// // res.send('post ok')
// // res.writeHead(302) //修改状态码
// // res.writeHead(304.{name:'nodejs'})
// res.redirect('/login') //重定向到/login
// })
app.listen(3000,()=>{
console.log('Server start')
})
116、获取静态资源的方式.mp4
//第一个参数是前缀可选 静态资源文件夹public
app.use('/static',express.static('public'))
const express=require('express')
const path=require('path')
const fs=require('fs')
//1.引入
const bodyParser=require('body-parser')
const app=express()
//注册到app
app.use(bodyParser.urlencoded({extended:false})) //false接收的值为字符串或者数组,true则为任意类型
app.use(bodyParser.json()) //解析json格式
//第一个参数是前缀可选 静态资源文件夹public
app.use('/static',express.static('public'))
app.all('/register',(req,res)=>{
if(req.method==='GET'){
let filePath=path.join(__dirname,'views','register.html')
let content=fs.readFileSync(filePath,'utf-8')
res.send(content)
}
else if(req.method==='POST'){
console.log(req.body)
res.redirect('/login')
}
})
app.get('/',(req,res)=>{
res.send('hello world')
})
app.get('/login',(req,res)=>{
let filePath=path.join(__dirname,'views','login.html')
let content=fs.readFileSync(filePath,'utf-8')
res.send(content)
})
app.listen(3000,()=>{
console.log('Server start')
})
117、art_template模板引擎的使用.mp4
使用Express渲染模板页面
art-template模板引擎
http://aui.github.io/art-template/zh-cn/express/index.html
安装
npm install art-template
npm install express-art-template
const express=require('express')
const path=require('path')
const fs=require('fs')
//1.引入
const bodyParser=require('body-parser')
const app=express()
//注册到app
app.use(bodyParser.urlencoded({extended:false})) //false接收的值为字符串或者数组,true则为任意类型
app.use(bodyParser.json()) //解析json格式
//第一个参数是前缀可选 静态资源文件夹public
app.use('/static',express.static('public'))
//引入 使用对应的引擎
app.engine('html',require('express-art-template'))
//项目环境设置 生产环境(线上)production 开发环境development
app.set('view options',{
debug:process.env.NODE_ENV !== 'development'
})
//设置在哪一个目录下查找模板文件
app.set('views',path.join(__dirname,'views'))
//设置模板的后缀名为html
app.set('view engine','html')
app.all('/register',(req,res)=>{
if(req.method==='GET'){
res.render('register')
}
else if(req.method==='POST'){
console.log(req.body)
res.redirect('/login')
}
})
app.get('/',(req,res)=>{
res.send('hello world')
})
app.get('/login',(req,res)=>{
res.render('login')
})
app.listen(3000,()=>{
console.log('Server start')
})
118、art_template模板引擎传递数据.mp4
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login</title>
</head>
<body>
<h1>登录页面</h1>
<img src="/static/img/3.jpg" alt="">
<p>My name is {{name}}</p>
<ul>
{{each arr}}
<li>{{$index}}-{{$value}}</li>
{{/each}}
</ul>
{{if age>18}}
{{/if}}
</body>
</html>
const express=require('express')
const path=require('path')
const fs=require('fs')
//1.引入
const bodyParser=require('body-parser')
const app=express()
//注册到app
app.use(bodyParser.urlencoded({extended:false})) //false接收的值为字符串或者数组,true则为任意类型
app.use(bodyParser.json()) //解析json格式
//第一个参数是前缀可选 静态资源文件夹public
app.use('/static',express.static('public'))
//引入 使用对应的引擎
app.engine('html',require('express-art-template'))
//项目环境设置 生产环境(线上)production 开发环境development
app.set('view options',{
debug:process.env.NODE_ENV !== 'development'
})
//设置在哪一个目录下查找模板文件
app.set('views',path.join(__dirname,'views'))
//设置模板的后缀名为html
app.set('view engine','html')
app.all('/register',(req,res)=>{
if(req.method==='GET'){
res.render('register')
}
else if(req.method==='POST'){
console.log(req.body)
res.redirect('/login')
}
})
app.get('/',(req,res)=>{
res.send('hello world')
})
app.get('/login',(req,res)=>{
let data={
name:'koo',
age:28,
arr:['vue','react','angular']
}
res.render('login',data)
})
app.listen(3000,()=>{
console.log('Server start')
})
119、路由接口的抽取工作.mp4
const express=require('express')
const path=require('path')
const fs=require('fs')
const passportRouter=require('./routes/passport')
const bodyParser=require('body-parser')
const app=express()
app.use(bodyParser.urlencoded({extended:false})) //false接收的值为字符串或者数组,true则为任意类型
app.use(bodyParser.json()) //解析json格式
app.use(passportRouter)
app.use('/static',express.static('public'))
app.engine('html',require('express-art-template'))
app.set('view options',{
debug:process.env.NODE_ENV !== 'development'
})
app.set('views',path.join(__dirname,'views'))
app.set('view engine','html')
app.get('/',(req,res)=>{
res.send('hello world')
})
app.listen(3000,()=>{
console.log('Server start')
})
//routes/passport.js
const express=require('express')
const router=express.Router()
router.all('/register',(req,res)=>{
if(req.method==='GET'){
res.render('register')
}
else if(req.method==='POST'){
console.log(req.body)
res.redirect('/login')
}
})
router.get('/login',(req,res)=>{
let data={
name:'koo',
age:28,
arr:['vue','react','angular']
}
res.render('login',data)
})
module.exports=router
122、pathinfo参数的获取.mp4
pathinfo/pathname风格的参数的获取
例如: /detail/1/economy (detail/:id/:type)
const express=require('express')
const path=require('path')
const app=express()
app.engine('html',require('express-art-template'))
app.set('view options',{
debug:process.env.NODE_ENV !== 'development'
})
app.set('views',path.join(__dirname,'views'))
app.set('view engine','html')
app.get('/list',(req,res)=>{
res.render('list')
})
app.get('/detail/:id/:type',(req,res)=>{
console.log(req.params)//{ id: '1', type: 'hot' }
res.send(`新闻${req.params.id}`)
})
app.listen(3000,()=>{
console.log('Server start')
})
<ul>
<li><a href="/detail/1/hot">新闻1</a></li>
<li><a href="/detail/2/flash">新闻2</a></li>
<li><a href="/detail/3/last">新闻3</a></li>
<li><a href="/detail/4/short">新闻4</a></li>
</ul>
124、模板继承的语法格式.mp4
//parent.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h2>header</h2>
{{block 'contentBloock'}}
<p>父中间</p>
{{/block}}
<h2>footer</h2>
</body>
</html>
{{extend './parent.html'}}
{{block 'contentBloock'}}
<p>子中间</p>
{{/block}}
const express=require('express')
const path=require('path')
const app=express()
app.engine('html',require('express-art-template'))
app.set('view options',{
debug:process.env.NODE_ENV !== 'development'
})
app.set('views',path.join(__dirname,'views'))
app.set('view engine','html')
app.get('/child',(req,res)=>{
res.render('child')
})
app.listen(3000,()=>{
console.log('Server start')
})
126、状态保持简介.mp4
三、状态保持技术cookie和session因为 http 是一种无状态协议,浏览器请求服务器是无状态的。
无状态:指一次用户请求时,浏览器、服务器无法知道之前这个用户做过什么,每次请求都是一次新的请求。
无状态原因:浏览器与服务器是使用socket套接字进行通信的,服务器将请求结果返回给浏览器之后,会关闭当前的 socket连接,而且服务器也会在处理页面完毕之后销毁页面对象。
有时需要保持下来用户浏览的状态,比如用户是否登录过,浏览过哪些商品等实现状态保持主要有两种方式:
在客户端存储信息使用 Cookie在服务器端存储信息使用 session
无状态协议:
1.协议对于事务处理没有记忆能力
2.对同一个 url 请求没有上下文关系
3.每次的请求都是独立的,它的执行情况和结果与前面的请求和之后的请求是无直接关系的,它不会受前面的请求应答情况直接影响,也不会直接影响后面的请求应答情况
4.服务器中没有保存客户端的状态,客户端必须每次带上自己的状态去请求服务器
5.人生若只如初见
127、设置和获取cookie信息.mp4
3.1,cookie特点:
1、cookie由服务器生成,保存在浏览器端的一小段文本信息2、cookie是以键和值得形式进行存储
3、浏览器在访问一个网站的服务器时,会自动在请求头中把和本网站相关的所有cookie发送给服务器4、cookie是基于域名安全的
5、cookie有过期时间,默认关闭浏览器之后过期
npm i cookie-parser
const express=require('express')
const path=require('path')
const cookieParser=require('cookie-parser')
const app=express()
app.use(cookieParser())
app.get('/set_cookie',(req,res)=>{
res.cookie('name','node',{maxAge:60*60*2}) //2分钟
})
app.get('/get_cookie',(req,res)=>{
let name=req.cookies['name']
console.log(name)
res.send('获取cookies:'+name)
})
app.listen(3000,()=>{
console.log('Server start')
})
128、cookie的特点介绍_交互流程图_.mp4
129、session的特点介绍_交互流程图_.mp4
3.2、session特点:
1、session数据保存在服务器端
2、session是以键和值的形式进行存储
3、session依赖于cookie,每个session信息对应的客户端的标识保存在cookie中
npm i cookie-session
130、session交互补充.mp4
131、设置和获取session信息.mp4
const express=require('express')
const cookieSession=require('cookie-session')
const app=express()
app.use(cookieSession({
name:'my_session',
keys:['#%$@$@%@$#@$@#$FSFSFSF'],//随便打 混淆
maxAge:1000*60*60*24*2 //2天
}))
app.get('/set_session',(req,res)=>{
req.session['name']='nodejs_session'
res.send('设置了session数据')
})
app.get('/get_session',(req,res)=>{
let name=req.session['name']
console.log(name)
res.send('获取session:'+name)
})
app.listen(3000,()=>{
console.log('Server start')
})
132、数据库简介.mp4
数据库有以下特点:
持久化存储
读写速度极高
保证数据的有效性
对程序支持性非常好,容易扩展
133、数据库管理系统和数据库分类.mp4
11 6 9 10.5
https://db-engines.com/en/ranking 数据库排名
134、关系型数据库核心元素和我们要学习的SQL语句.mp4
每一行称为记录
每一列称为字段
整个exl文件就好比一个数据库,exl文件中的Sheel就好比一张张表
4.5,SQL SQL语句的作用是实现数据库D客户端和服务端之间的通信.其表现口形式为:D带有一定格式的字符串.
1970年E.F.Codd的《A Relational Modelof Data forLarge Shared Data Banks》的论文开始讲起。该论文奠定了关系模型的理论基础,Codd的同事DonChamberlin对Codd的论文和关系运算进行转换,发明了简单易用的SQL语言,并且在之后的发展中成为所有关系型数据库的标准。
SQL(Structured Query Language)是结构化查询语言,是一种用来操作RDBMS的数据库语言。当前几乎所有关系型数据库都支持使用SQL语言进行操作,也就是说可以通过SQL操作oracle,sql server,mysql,sqlite等等所有的关系型的数据库。
SQL语句主要分为:
DQL:数据查询语言,用于对数据进行查询,如select
DML:数据操作语言,对数据进行增加、修改、删除,如insert、udpate、delete
TPL:事务处理语言,对事务进行处理,包括begin transaction,commit,rollback
DCL:数据控制语言,进行授权与权限回收,如grant,revoke
DDL:数据定义语言,进行数据库、表的管理等,如create、drop
对于web程序员来讲,重点是数据的crud(增删改查),必须熟练编写DQL,DML,能够编写DDL完成数据库、表的操作,其它语言如TPL,DCL、CCL了解即可.
DBA职业 数据库
135、解压mysql压缩包.mp4
136、安装mysql.mp4
137、启动mysql服务_配置环境变量.mp4
二、使用
启动、停止、卸载mysq]服务的命令
1.启动:net start mysql
2.停止:net stop mysql
3.卸载:mysqld-remove
139、安装navicat.mp4
140、navicat的界面操作.mp4
show tables;
141、数据类型和约束.mp4
注意:不区分大小写
五、数据类型和约束
常用数据类型如下:
整数:int,bit
小数:decimal
字符串:varchar,char
日期时间:date,time,datetime
枚举类型(enum)
特别说明的类型如下:
decimal表示浮点数,如 decimal(5,2)表示共存5位数,小数占 2 位.
char表示固定长度的字符串,如char(3),如果填充'ab'时会补一个空格为'ab '.
varchar表示可变长度的字符串,如varchar(3),填充'ab'时就会存储"ab'
对于图片、音频、视频等文件,不存储在数据库中,而是上传到某个服务器上,然后在表中存储这个文件的保存路径.
字符串 text 表示存储大文本,当字符大于 4000 时推荐使用,比如技术博客.
Navicat 8 for MySQL
数据约束:
约束本质上是对数据在数据类型限定的基础上添加的额外的要求.
常见的约束如下:
1.主键 primary key:物理上存储的顺序.MySQL 建议所有表的主键字段都叫 id,类型为 int unsigned.
2.非空not null:此字段不允许填写空值.
3.惟一unique:此字段的值不允许重复.
4,默认default:当不填写字段对应的值会使用默认值,如果填写时以填写为准.
5,外键foreign key:对关系字段进行约束,当为关系字段填写值时,会到关联的表中查询此值是否存在,如果存在则填写成功,如果不存在则填写失败并抛出异常.(仅做了解)
142、mysql命令_操作数据库.mp4
-- 链接数据库
mysql -uroot -p
-- 退出数据库
quit/exit
-- 显示数据库版本
select version();
-- 查看当前使用的数据库
select database();
-- 查看所有数据库
show databases;
-- 创建数据库
create database kuname charset=utf8;
-- 查看创建数据库的语句
show create database kuname;
-- 使用数据库
use kuname
-- 查看数据库的表
show tables;
-- 删除数据库
drop database kuname;
有一些不加分号;
D:\phpstudy_pro\Extensions\MySQL5.7.26\bin>
143、mysql命令_创建数据表.mp4
-- 数据表的操作
-- 查看当前数据库中所有表
show tables;
创建表
-- int unsigned 无符号整形
-- auto_increment 表示自动增长跟主键在一起
-- not null 表示不能为空
-- primary key 表示主键
-- default 默认值
-- create table 数据表名字(字段 类型 约束[,字段 类型 约束]);
create table test(name varchar(30) not null,age int unsigned);
-- 查看表结构
desc test;
create table classes(id int unsigned primary key auto_increment,name varchar(39) not null);
create table students(id int unsigned primary key auto_increment,name varchar(30) not null,age int unsigned,high decimal(3,2),gender enum("男","女","保密","中性") default "保密",cls_id int unsigned);
144、mysql命令_修改表结构.mp4
-- 查看表的创建语句
show create table students;
-- 修改表-添加字段mascot(吉祥物)
-- alter table 表名 add 列名 类型;给classes表添加mascot字段
alter table classes add mascot varchar(50);
-- 修改表-修改字段:不重命名版
-- alter table 表名 modify 列名 类型及约束;
alter table classes modify mascot varchar(100);
-- 修改表-修改字段:重命名版
-- alter table 表名 change 原名 新名 类型及约束;
alter table classes change mascot jxw int unsigned;
-- 修改表-删除字段
-- alter table 表名 drop 列名;
alter table classes drop jxw;
-- 删除表
-- drop table 表名;
-- drop database 数据库;
drop table test;
145、mysql命令_插入数据.mp4
-- 查询表内容
select * from students;
-- 全列插入
-- insert into 表名(字段1,字段2)values(值1,值2);
-- 主键字段 可以用 0 null default 来占位
-- 向classes表中插入 一个班级
> insert into classes(id,name) values(1,"koo");
-- 全部插入
-- insert into 表名 values(值1,值2,值3...)
insert into students values(1,"koo",18,1.70,"男",1);
-- 部分插入
-- insert into 表名(列1,...)values(值1,...)
-- 多行插入
-- insert into 表名(列1)values(值),(值);
insert into students(name) values("yoo"),("mia");
不能单引号
146、mysql命令_修改表数据.mp4
-- 修改
-- 全部修改
update students set age=16;
-- 按条件修改
> update students set age=28 where id=1;
-- 按条件修改多个值
update students set age=29,high=1.80 where id=1;
147、mysql命令_基本查询用法.mp4
select * from students;
select * from students where id=1;
select name,age from students;
select name,age from students where id=1;
select name as "姓名",age as "年龄" from students; -- 起别名
148、mysql命令_删除语句.mp4
物理删除
delete from students where id=4;
逻辑删除
逻辑删除
用一个字段来表示 这条信息是否已经不能再使用了
给students表添加一个 is_delete 字段 bit 类型
alter table students add is_delete bit default 0;
update students set is_delete=1 where id=3;
149、数据库操作前准备工作.mp4
150、查询基本用法2.mp4
select students.name from students;
select s.name,s.age from students as s;
//消除重复行
select distinct gender from students;
151、比较运算符和逻辑运算符.mp4
select * from students where age>=18;-- > < >= != or <>
-- 逻辑运算符
-- and / between..and
-- 18和28之间的所有学生信息
select * from students where age>=18 and age<=28;
select * from students where age between 18 and 28;
select * from students where age>18 and gender="女";
select * from students where age>18 and gender=2; -- 枚举的数据类型可以用数字来表示,数字从1开始
select * from students where age>18 or height>=180.00;
select * from students where not (age>18 and gender=2);
153、模糊查询.mp4
-- 模糊查询(where name like 要查询的数据)
-- like
-- %替换任意个
-- _替换1个
-- 查询姓名中 以“小"开始的名字的学生信息
select * from students where name like "小%":
select * from students where name like "__":
154、范围查询.mp4
-- 范围查询
-- in(1,3,8)表示在一个非连续的范围内
-- 查询 年龄为18或34的姓名的学生信息
select * from students where age in (18,34); -- (18,34)不是区间,是确切的值
-- not in 不非连续的范围之内
-- 年龄不是 18或34岁的学生信息
select * from students where age not in (18,34);
-- between...and...表示在一个连续的范围内
-- 查询 年龄在18到34之间的学生信息
select * from students where age between 18 and 34;
select * from students where age not between 18 and 34;
-- 判断is null
select * from students where height is null;
select * from students where height is not null;
155、排序查询.mp4
排序
order by 字段
asc asc从小到大排列,即升序
desc desc从大到小排序,即降序
查询年龄在18到34岁之间的男性,按照年龄从小到大到排序
select * from students where gender=1 and age between 18 and 24 order by age asc;
select * from students where gënder=2 and age between 18 and 34 order by height desc, age asc;
157、分组查询.mp4
select gender from students group by gender;-- 可以消除重复
select gender, count(*) from students group by gender;
select gender,group_concat(name) from students group by gender;
-- 平均年龄
select gender,avg(age) from students group by gender;
having(注意having和group by 连用 having后通常也要跟 聚合函数)
注意:聚合函数如果做为条件出现,只能和having配合。不能和where配合使用。
查询平均年龄超过30岁的性别,以及姓名
select gender,avg(age) from students group by gender having avg(age)>30;
158、分页查询.mp4
分页
limit start,count
limit 放在最后面(注意)
limit(要显示第几页-1)*每页分多少个,每页分多少个;
select * from students limit 2;
===
select * from students limit 0,2;
select * from students order by age asc limit 10, 2;
160、连接查询.mp4
连接查询(表与表之间的链接,为了更好的查出有效数据)
inner join...on select...from 表A inner join 表B;
查询 有能够对应班级的学生以及班级信息
select * from students inner join classes;
select * from students inner join classes on students.cls_id=classes.id;
161、子查询.mp4
select * from students where height>(select avg(height) from sudents);
162、使用mysql模块来获取数据库里面的数据.mp4
npm i mysql
var mysql=require('mysql')
var pool=mysql.createPool({
host:"localhost",
user:"root",
password:"root",
database:"kuname"
})//数据库连接配置
function query(sql,callback){
pool.getConnection(function(err,connection){
connection.query(sql,function(err,rows){
callback(err,rows)
connection.release()
})
})
}//对数据库进行增删改查操作的基础
exports.query=query
const express=require('express')
const db=require('./db/db')
const app=express()
app.get('/get_data',(req,res)=>{
db.query('select * from students',(err,data)=>{
console.log(data)
res.send(data)
})
})
app.listen(3000,()=>{
console.log('Server start')
})
163、orm简介.mp4
ORM 介绍
ORM全拼Object-Relation Mapping.
中文意为 对象-关系映射.
主要实现模型对象到关系数据库数据的映射.
比如:把数据库表中每条记录映射为一个模型对象
优点:
1、只需要面向对象编程,不需要面向数据库编写代码.
2、对数据库的操作都转化成对类属性和方法的操作3、不用编写各种数据库的sql语句.
4、实现了数据模型与数据库的解耦,屏蔽了不同数据库操作上的差异.
5、不在关注用的是mysql、oracle…..等.
6、通过简单的配置就可以轻松更换数据库,而不需要修改代码.
缺点:
1、相比较直接使用SQL语句操作数据库,有性能损失.
2、根据对象的操作转换成SQL语句,根据查询的结果转化成对象,在映射过程中有性能损失.
3、有局限性,ORM中没有提供的查询功能需要写会sql语句
一条记录映射为(当做)一个对象,字段映射为属性
164、使用orm来获取数据库里面的数据.mp4
165、使用orm查询操作.mp4
167、使用orm增加数据.mp4
168、使用orm删除数据.mp4
169、使用orm修改数据和执行自定义sql语句.mp4
nodejs-orm
170、async_await版本.mp4
171、捕获异常的版本.mp4
172、提取handleDB的代码.mp4
174、封装操作数据库的函数handleDB.mp4
175、webA的执行流程.mp4
176、webA登录流程的补充说明.mp4
177、CSRF跨站请求伪造的流程图解析.mp4
三、CSRF跨站请求伪造
CSRF全拼为Cross Site Request Forgery,译为跨站请求伪造。
I CSRF指攻击者盗用了你的身份,以你的名义发送恶意请求。
包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账.....
造成的问题:个人隐私泄露以及财产安全。
178、CSRF跨域请求伪造防护流程图解析.mp4
179、CSRF跨站请求伪造防护代码书写.mp4
181、csrf项目中使用的通用版本.mp4
9 10.5 11 6
路由钩子
182、模板和静态资源的处理.mp4
183、项目初始化和模板的设置.mp4
184、cookie和session的配置和测试.mp4
185、项目配置信息额抽取.mp4
186、端口抽取和路由接口函数的抽取.mp4
187、项目数据表的分析.mp4
188、分析news_sql.mp4
189、创建数据库后_第一种方式导入数据.mp4
190、第二种方式导入数据.mp4
mysql> source C: \Users\VULCAN\Desktop\news. sql
191、使用数据库操作函数handleDB.mp4
192、验证码文本和图片的生成.mp4
九、初步获取图片验证码先安装验证码获取的模块,在项目目录下:
yarn add svg-captcha
193、图片验证码的展示工作.mp4
195、补充图片验证码保存到session中.mp4
196、注册功能的前端代码分析.mp4
197、注册功能后端流程的分析.mp4
198、注册功能后端代码实现01.mp4
199、注册功能的后端代码的实现02.mp4
200、测试注册的功能.mp4
201、登录功能前端代码的分析.mp4
202、登录功能后端业务分析.mp4
203、登录功能后端代码的实现.mp4
204、首页登录状态的展示.mp4
205、退出登录接口完成.mp4
206、给用户设置最后一次登录时间.mp4
207、首页头部分类完成.mp4
208、右侧点击排行的新闻标题展示.mp4
210、右侧点击排行的样式解决.mp4
211、给每一个post请求添加CSRF防护功能.mp4
212、Base64的讲解.mp4
Base64 的由来
目前 Base64 已经成为网络上常见的传输 8bit 字节代码的编码方式之一。在做支付系统时,系统之间的报文交互都需要使用Base64对明文进行转码,然后再进行签名或加密,之后再进行(或再次Base64)传输。那么,Base64 到底起到什么作用呢?
在参数传输的过程中经常遇到的一种情况:使用全英文的没问题,但一旦涉及到中文就会出现乱码情况。与此类似,网络上传输的字符并不全是可打印的字符,比如二进制文件、图片等。Base64的出现就是为了解决此问题,它是基于64个可打印的字符来表示二进制的数据的一种方法。
电子邮件刚问世的时候,只能传输英文,但后来随着用户的增加,中文、日文等文字的用户也有需求,但这些字符并不能被服务器或网关有效处理,因此Base64就登场了。随之,Base64在URL,Cookie、网页传输少量二进制文件中也有相应的使用。
213、加密的一些信息介绍.mp4
214、单向散列函数的介绍.mp4
215、对称加密.mp4
216、非对称加密.mp4
217、md5的使用.mp4
yarn add md5
双重md5加盐加密的处理方式。
218、项目中使用思路和流程.mp4
md5(md5('hello')+'^$#%@$%@$%$%$')
219、项目中使用md5并且抽取keys.mp4
220、Restful风格的接口介绍.mp4
三、RESTful风格接口
RESTful中REST,即Representational State Transfer的缩写(译为"表现层状态转化")
访问一个网站,就代表了客户端和服务器的一个互动过程。在这个过程中,势必涉及到数据和状态的变化。
互联网通信协议HTTP协议,是一个无状态协议。这意味着,所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"(State Transfer)。而这种转化是建立在表现层之上的,所以就是"表现层状态转化"。
客户端用到的手段,只能是HTTP协议。具体来说,就是HTTP协议里面,四个表示操作方式的动词:GET POST,PUT,DELETE。它们分别对应四种基本操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源。
特点:
(1)每一个URI代表一种资源;
(2)客户端和服务器之间,传递这种资源的某种表现层;
(3)客户端通过四个HTTP动词,对服务器端资源进行操作,实现"表现层状态转化"。
221、Resful风格接口的体验.mp4
222、JWTtoken三大部分介绍.mp4
四、Json Web Token(JWT)的介绍
JSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用JWT在两个组织之间传递安全可靠的信
yarn add jsonwebtoken
Header
Payload 载荷
Signature 签名
223、jwt验证签名原理.mp4
224、生成jwt_token的接口书写.mp4
225、postman的使用.mp4
226、首页新闻列表的展示需求.mp4
227、首页新闻列表前端代码分析.mp4
228、首页新闻列表后端分析.mp4
229、首页新闻列表后端代码编写.mp4
230、首页新闻列表加载更多的前端分析.mp4
231、首页新闻列表加载更多的后端代码编写.mp4
232、详情页的准备工作完成.mp4
233、详情页面模板继承.mp4
234、详情页右上角登录展示和点击排行数据展示.mp4
235、index页面的模板继承.mp4
236、详情页的新闻内容的查询.mp4
237、把查询到的数据填充到详情页.mp4
238、新闻页面点击数量加1.mp4
239、获取登录用户的信息函数的抽取.mp4
240、404页面的抽取工作.mp4
241、其他情况的404页面的返回.mp4
243、收藏和以收藏按钮的展示功能完成.mp4
244、点击收藏和取消收藏的后端分析.mp4
245、点击收藏和取消收藏的前端分析.mp4
246、点击收藏和取消收藏实现01.mp4
247、点击收藏和取消收藏实现02.mp4
248、点击收藏和取消收藏的功能测试完成.mp4
249、评论功能的演示_及表字段的分析.mp4
250、评论和回复的传参的分析.mp4
251、评论的业务流程分析.mp4
252、在数据中添加一条评论.mp4
253、把评论数据数据传到ajax回调函数中.mp4
254、刷新之后评论功能的展示.mp4
255、评论功能最终完成.mp4
256、回复的ajax的展示.mp4
257、解决刷新报错的问题_回复功能完成_
258、复习回顾.mp4
259、点赞功能的演示.mp4
260、点赞的前端分析.mp4
261、点赞业务流程分析.mp4
262、点赞和取消点赞后端代码实现01.mp4
263、点赞和取消点赞后端代码实现02.mp4
264、刷新展示用户是否点赞的思路分析.mp4
265、点赞功能完成.mp4
266、详情页右侧作者名片数据查询.mp4
267、作者粉丝数量查询.mp4
268、完成关注按钮的展示.mp4
269、关注和取消关注的前端分析.mp4
270、关注和取消关注完成.mp4
271、个人中心页面展示.mp4
272、设置登录才可以访问个人中心页面.mp4
273、个人中心页面模板的抽取和登录状态保持设置.mp4
274、子页面的展示问题.mp4
275、基本资料的数据展示.mp4
277、修改用户基本数据后端完成.mp4
279、测试用户基本数据的修改_前端处理_.mp4
280、修改密码页面的展示.mp4
281、修改密码后端分析.mp4
282、修改密码后端代码完成.mp4
283、修改密码功能测试完成.mp4
284、抽取登录用户信息_可以获取到的用户信息_.mp4
285、展示修改头像页面.mp4
286、上传头像的流程图.mp4
287、图片上传到后台服务器.mp4
四、头像上传接口初步使用
安装:yarn add multer
288、七牛云的对象存储空间的创建.mp4
qiniu.com
289、上传图片到七牛云服务器.mp4
290、上传头像接口完成.mp4
291、头像链接的渲染工作.mp4
293、头像渲染完成.mp4
294、我的收藏页面展示.mp4
295、pagination前端分页的分析.mp4
296、分页的当前页和总页数的展示.mp4
297、收藏新闻的数据展示.mp4
298、项目总结.mp4
二、项目总结
《经济新闻网》一款新闻展示的Web项目,主要为用户提供最新的金融资讯、数据
以抓取其他网站数据和用户发布作为新闻的主要来源
基于express 框架,以 前后端不分离 的形式实现具体业务逻辑
数据存储采用mysql,使用orm
封装自己的操作数据可的工具函数handleDB(兼容其他node框架)
用户图片数据使用对象存储(七牛云)
采用session实现保持用户登录状态机制
实现对CSRF请求伪造进行防护功能
(提供jwt的获取接口)
采用art-template 模板引擎技术
界面局部刷新使用 ajax 请求接口
实现模块:注册、登录、首页新闻数据展示模块,滑动到底部加载更多、点击排行、基页模板的抽取与模板继承、详情页数据展示、用户收藏新闻、用户评论模块、回复评论模块、新闻作者数据展示、用户关注模块、个人中心模块(修改基本资料、密码、用户头像)等。
299、跨域的概念及现象和本质.mp4
300、jsonp原理.mp4
八、JSONP介绍
处理使用ajax代码发起请求外,页面某些标签也会自动发起请求。我们可以利用script标签的src属性,来发起请求。
jsonp 就是前端利用script 在页面不刷新的情况下和服务器进行交互一种技术。拿 json 格式的数据去填充一个函数,英语:json with paddding a function 简称:jsonp
301、跨域和jsonp的流程图.mp4
302、express提供的jsonp方法.mp4
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
</head>
<body>
<h3 class="name"></h3>
<h4 class="age"></h4>
<script>
function callback(data){
$('.name').html(data.name)
$('.age').html(data.age)
}
</script>
</body>
<script src="http://127.0.0.1:3000/data?callback=callback"></script>
<!-- 第一个callback是固定的写法,第二个callback是要执行的这个函数名称 -->
</html>
const express=require('express')
const app=express()
app.get('/data',(req,res)=>{
let data={
name:'nodejs',
age:11
}
//res.setHeader('Access-Control-Allow-Origin','*')
res.jsonp(data)
})
app.listen(3000,()=>{
console.log('Server start!')
})
303、在后端设置响应头Access_Control_Allow_Origin解决跨域.mp4
304、使用cors包来解决跨域.mp4
'yarn add cors
305、模块化注意事项.mp4
注意要点:
1、CommonJs 的规范中,需要使用其他模块的数据的时候,引入的关键方法是require
2、require("./modules/m1.js");参数可以是相对路径(./不能省略),也可以是绝对路径3、模块的扩展名(.js)可以不写,也可以写
4、导出之后一般有一个常量来接收(const常量名),常量名一般和模块名一致(不一致也不会报错)
306、express中间件洋葱执行原理.mp4 koa
一、简介
Koa 是现在最流行的基于Node.js平台的web开发框架。
kda 是由 Express 原班人马打造的
致力于成为一个更小、更富有表现力、更健壮的 Web 框架。
koa 不在内核方法中绑定任何中间件,它仅仅提供了一个轻量优雅的函数库,使得编写 Web 应用变得得心应手。
官网:https://koajs.com/
中文社区:https://www.koajs.com.cn/
307、koa路由中间件使用.mp4
三、路由中间件
koa-router
yarn add koa-router
308、koa的数据库操作.mp4
309、koa介绍和helloworld代码.mp4
const Koa=require('koa')
const Router=require('koa-router')
const app=new Koa()
const router=new Router()
//不写第一个参数路径 全部都响应
// app.use(async ctx=>{ //req,res context
// console.log(ctx.request.url)
// console.log(ctx.req.url)
// console.log(ctx.url)
// console.log(ctx.req.method)
// ctx.body='hello world'
// })
router.get('/data',ctx=>{
console.log(ctx.request.url,ctx.req.url,ctx.url)
console.log(ctx.req.method)
ctx.body='hello world'
})
app.use(router.routes())
app.listen(3000,()=>{
console.log('Server start')
})

浙公网安备 33010602011771号