Shu-How Zの小窝

Loading...

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

https://www.npmjs.cn/

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

https://www.cmd5.com

双重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')
})
posted @ 2024-12-12 11:04  KooTeam  阅读(71)  评论(0)    收藏  举报