php开发技术栈: LAMP - Linux Apache MySQL PHP
node.js 全栈开发技术栈: MEAN - MongoDB Express Angular Node.js
REPL 全称 read eval print loop (交互式解释器)
R 读取
E 执行
P 打印
L 循环
在REPL中编写程序(类似于F12 console控制台)
node
命令进入REPL环境.exit
读取文件
var fs = require('fs')
fs.readFile('路径',(err,data)=>{
if(err) throw err;
cl(data.toString('utf-8'))
})
__dirname和__filename获取正在执行的js文件路径
这两个东西, 不算是全局的 相当于本地的 会在当前js中产生一个闭包吧他们传进去
通过path模块进行路径拼接
path.join(__dirname,'hello.txt');
error-first介绍(错误优先)
见: 搭建一个简单的http服务程序.js
通过服务区端设置响应报文头来解决乱码问题
response.setHeader('Content-Type','text/plain; charset=utf-8');
http响应报文头 作用 告诉浏览器发送数据的其他相关信息
根据不同请求做出不同的响应
response.setHeader('Content-Type','text/html; charset=utf-8');
异步操作, try-catch是无法捕获异常的
对于异步操作, 要通过判断错误号(err.code)来进行出错出处理
通过mime 可以根据后缀 得到mime type
在请求服务器的时候, 请求的 url 就是一个标识
res.write()
res.end() 结束响应(请求)
res.setHeader('Content-Type': 'text/html') 设置响应报文头
res.statusCode = 404; 设置 http 响应状态码
res.statusMessage = 'Not Found'; 设置 http 响应状态码对于信息
res.writeHead() 直接向客户端响应(写入)响应报文头
res.writeHead(404,'Not Found',{
'Content-Type': 'text/html'
})
res.setHeader方法 和 res.writeHead方法 区别
npm -v
npm install npm@latest -g
npm install 包名
安装---- 本地安装
npm install mime -g
mime a.txt
安装完毕后可以在命令行中直接使用(本质)
npm全局安装世纪做了两件事:
元数据: 描述自身的数据
如何创建
npm init
或者npm init -y
或者npm init -yes
命令注意
记录了要安装包的所有信息 可以加快安装速度
路由组成: 请求方法 请求路径
str.startwith('xx') //字符串方法 以xx开头 返回boolean
const url = require('url');
const urlObj = url.parse(req.url, true); // 返回包含url所有内容的对象 第二个参数为true 可以让urlObj.jquery内容转为json对象
req.query 获取? 后面的数据
restful形式的接口
服务器想让浏览器做什么事情 通过传递响应报文头来实现
const _ = require('underscore');
_.zip
const html = '<%= name %>';
const fn = _.template(html)
html = fn({name:'哈哈'}) // 哈哈
封装异步代码 需要一个回调函数
1.核心模块, 内置模块, 原生模块
2.文件模块
如果加载时没有指定后缀名,name按照如下顺序依次加载响应模块
注意:文件模块加载 最好带后缀名
3.自定义模块
情况一: require() 参数是一个路径
情况二: require() 参数是一个模块名称
总结: commonJS 是为JavaScript 语言判定的一种 模块规范, 编程 API规范
一. 类型介绍
二. 创建一个Buffer对象
var buf = Buffer.from('你好!');
console.log(buf);
console.log(buf.toString('utf8'));
三. Buffer 对象与编码
node.js目前支持的编码:
nodemon
工具来自动重启web服务器npm i nodemon -g
全局安装即可;node 要执行的文件路径
来运行 Node.js 代码;nodemon 要执行的文件路径
来运行 Node.js 代码;nodemon
来启动 web 服务器定义(什么是Express):一个快速的网站开发框架,封装了原生的http模块,用起来更方便;API更人性化
npm i express -S
即可安装express
服务器:
express
第三方模块;const app = express()
方法;app.get()
或 app.post()
方法,来监听客户端的 get
或 post
请求,具体语法:
GET
请求:app.get('请求地址', (req, res) => { 处理函数 })
POST
请求: app.post('请求地址', (req, res) => { 处理函数 })
app.listen(端口, IP地址, 启动成功后的回调函数)
启动服务器;res.send()
Content-Type: text/html;
Content-Type: application/json
res.sendFile()
res.sendFile(path.join(__dirname, './view/index.html'))
res.sendFile('./view/movie.html', { root: __dirname })
res.sendFile()
可以向浏览器发送 静态页面;res.send()和res.end()区别
res.end()用于快速响应,没有数据返回到客户端
res.send()有数据返回到客户端
res对象的常见方法
res.json() 等价于 res.send(json)
res.sendFile() 读取文件并响应
res.redirect() 重定向
res.status(404).end('文件不存在')
express.static()
快速托管静态资源如果我们网站中,有很多静态资源需要被外界访问,此时,使用 res.sendFile 就有点力不从心了;
这时候,express 框架,为我们提供了
express.static('静态资源目录')
来快速托管指定目录下的所有静态资源文件;
app.use(express.static('public'));
app.use()
方法,是专门用来注册 中间件;express.static
是express的内置中间件;app.use('/虚拟目录', express.static('public'))
npm i ejs -S
app.set('view engine', 'ejs')
app.set('views', './views')
res.render('index.ejs', { 要渲染的数据对象 })
,注意,模板页面的 后缀名,可以省略不写!安装 两个包 cnpm i art-template express-art-template -S
自定义一个模板引擎 app.engine('自定义模板引擎的名称', 渲染函数)
将自定义的模板引擎,配置为 express 的默认模板引擎 app.set('view engine', '具体模板引擎的名称')
配置 模板页面得存放路径 app.set('views', '路径')
js
// 1. 封装单独的 router.js 路由模块文件
const express = require('express')
// 创建路由对象
const router = express.Router()
router.get('/', (req, res)=>{})
router.get('/movie', (req, res)=>{})
router.get('/about', (req, res)=>{})
// 导出路由对象
module.exports = router
js
// 导入自己的路由模块
const router = require('./router.js')
// 使用 app.use() 来注册路由
app.use(router)
注册路由方式
通过 正则 注册路由
1,方式是 get
2,请求路径以/index开头即可
app.get(/^\/index(\/.+)*$/,(req, res)=>{
res.send('hi!');
})
定义:中间件就是一个处理函数;只不过这个函数比较特殊,包含了三个参数,分别是
req
,res
,next
注意:中间件方法中的三个参数:
- req:请求对象;
- res:响应对象;
- next:next()可以被调用,表示调用下一个中间件方法;
app.get('URL地址', (req, res, next)=> {})
;router.get('url地址', (req, res, next)=>{})
app.use((err, req, res, next)=>{})
express.static()
body-parser
解析post 表单数据中间件的概念,了解即可,因为实际开发中,我们都直接使用第三方现成的中间件;
获取 http://127.0.0.1:3001/user?id=10&name=zs
中的查询参数:
req.query
获取参数即可;查询字符串
传递的参数,express 框架会直接解析,大家只需要使用 req.query
直接获取 URL 中 查询字符串的参数;从URL地址中获取路径参数:
app.get('/user/:id/:name', (req, res) => {})
http://127.0.0.1:3001/user/10/zs
req.params
可以获取URL地址中传递过来的参数;通过 req.params 获取路由中的参数
app.get('/news/:yeas/:month/:day',(req, res)=>{
res.send(req.params);
})
从post表单中获取提交的数据:
body-parser
来解析表单数据npm i body-parser -S
const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({ extended: false }))
req.body
来访问解析出来的数据跨域资源共享
,需要服务器端进行 CORS
配置;cors
的模块即可;请求 - 处理 - 响应
的!cookie
,这样,每次发送请求,都会把这个cookie随同其他报文一起发送给服务器,服务器可以根据报文中的cookie,区分不同的客户端浏览器。writeHeader
的时候,通过Set-Cookie
来将cookie标识通过响应报文发送给客户端!jquery.cookie
这个插件!var http = require('http');
var server = http.createServer();
server.on('request', function (req, res) {
// 解析cookie
var cookies = {};
var cookieStr = req.headers.cookie; // 从请求的headers中获取cookie信息
cookieStr && cookieStr.split(';').forEach(function (item) {
var parts = item.split('=');
cookies[parts[0].trim()] = parts[1].trim(); // 将cookie解析出来,保存到对象中
});
res.writeHeader(200, {
'Content-Type': 'text/plain; charset=utf-8',
"Set-Cookie": ['issend=ok', 'age=20']
});
if(cookies.issend ==='ok'){
res.end('不要太贪心哦!');
}else{
res.end('呐,赏你一朵小红花~~');
}
});
server.listen(4000, function () {
console.log('服务器已启动!');
});
expires
设置Cookie的过期时间// 设置 过期时间 为60秒之后
// 注意:在设置过期时间的时候,需要将时间转换为 UTC 格式
var expiresTime = new Date(Date.now() + 1000 * 60).toUTCString();
res.writeHeader(200, {
'Content-Type': 'text/html; charset=utf-8',
'Set-Cookie': ['isvisit=true;expires=' + expiresTime, 'test=OK']
});
res.end('你好,欢迎光临,送给你一个苹果!
');
GMT和UTC有什么区别?格林尼治标准时(GMT)与世界时(UTC)是怎么回事
使用谷歌插件edit this cookie
,就能伪造cookie数据!所以不要使用cookie存储敏感的数据!比如登录状态和登录信息;
一些敏感的数据,应该存储都服务器端!
express-session
来保存登录状态由于HTTP是无状态的,所以服务器在每次连接中持续保存客户端的私有数据,此时需要结合cookie技术,通过session会话机制,在服务器端保存每个HTTP请求的私有数据;
在服务器内存中开辟一块地址空间,专门存放每个客户端私有的数据,每个客户端根据cookie中保存的私有sessionId,可以获取到独属于自己的session数据。
安装session模块npm install express-session -S
导入session模块
var session = require('express-session')
在express中使用session
中间件:
// 启用 session 中间件
app.use(session({
secret: 'keyboard cat', // 相当于是一个加密密钥,值可以是任意字符串
resave: false, // 强制session保存到session store中
saveUninitialized: false // 强制没有“初始化”的session保存到storage中
}))
将私有数据保存到当前请求的session会话中:
// 将登录的用户保存到session中
req.session.user = result.dataValues;
// 设置是否登录为true
req.session.islogin = true;
通过destroy()
方法清空session
数据:
req.session.destroy(function(err){
if(err) throw err;
console.log('用户退出成功!');
// 实现服务器端的跳转,这个对比于 客户端跳转
res.redirect('/');
});
彩虹表
;bcrypt
加密算法,得到加密之后的密文进行存储;幂次
;$版本号$循环的幂次$22位的随机盐 31位的密文
随机盐
和加密的幂次
,和加密算法的版本号
已经被存储到了真正的密文中;运行 npm i node-pre-gyp -g
在项目根目录中,打开终端,运行 cnpm install bcrypt -S
导入 bcrypt
// 导入加密的模块
const bcrypt = require('bcrypt')
定义幂次:
// 定义一个 幂次
const saltRounds = 10 // 2^10
调用 bcrypt.hash()
加密:
// 加密的方法
bcrypt.hash('123', saltRounds, (err, pwdCryped) => {
console.log(pwdCryped)
})
调用bcrypt.compare()
对比密码是否正确:
// 对比 密码的方法
bcrypt.compare('123', '$2b$10$i1ufUKnC9fXTsF9oqqvLMeDnpNfYIvhyqKRG03adiebNFPkjW3HPW', function(err, res) {
console.log(res)
// 内部对比的过程:
// 1. 先获取 输入的明文
// 2. 获取输入的密文
// 2.1 从密文中,解析出来 bcrypt 算法的 版本号
// 2.2 从密文中,解析出来 幂次
// 2.3 从密文中,解析出来前 22 位 这个随机盐
// 3. compare 方法内部,调用 类似于 hash 方法 把 明文,幂次,随机盐 都传递进去 最终得到正向加密后的密文
// 4. 根据最新得到的密文,和 compare 提供的密文进行对比,如果相等,则 返回 true ,否则返回 false;
})
在PHP中,抽取公共的区域,直接使用PHP语法就行;
但是,在Express的框架中,并没有抽取页面公共部分的语法,需要模板引擎提供这样的语法;
markdown + editor
=> mditor
mditor
这个第三方模块,提供了两个功能:require('mditor')
,使用这个模块,提供的方法,把markdown
文本,解析转换为HTML
内容;