当前位置:网站首页>实战美团Nuxt +Vue全家桶,服务端渲染,邮箱验证,passport鉴权服务,地图API引用,mongodb,redis等技术点
实战美团Nuxt +Vue全家桶,服务端渲染,邮箱验证,passport鉴权服务,地图API引用,mongodb,redis等技术点
2022-08-02 14:09:00 【N.S.N】
koa
koa-generator
- 直接创建koa项目,不需要自己配置
- 全局安装
npm i -g koa-generator
- 创建项目
koa2 -e project
其中-e
表示以ejs
为模板 nodemon
node不需要重新执行,自动加载程序
mongodb
- 启动 两个命令行,分别输入
mongod --dbpath 数据存储地址
mongo
启动数据库
mongoose 是操作MongoDB的库,
const mongoose = require('mongoose')
mongoose.connect('mongodb://127.0.0.1:27017/数据库')
let schema = new mongoose.Schema({
name: String}) //定义字段的数据类型
let Person = mongoose.model('name',schema) //创建数据模型
let name = new Person({
name:'fhx'}) //成功创建数据库,并添加数据成功
name.save() //添加数据后必须执行这段代码,
Person.find({
name:''})
Person.findOne({
name:''}) //对数据库的增删改查都是对模型的操作
Person.where().remove() //删
Person.where().update() //改
Person.create({
}) //增
### redis
+ 启动 在redis的根目录中,输入redis-server
+ redis是一个数据库,存储的数据为键值对
+ koa连接session
安装
npm i koa-generic-session
npm i koa-redis //如果npm安装错误,则使用cnpm
代码
const session = require('koa-generic-session')
const Redis = require('koa-redis')
app.keys = ['jk','ff'] //对session加密,并随便添加两个字符串
app.use(session({
store: new Redis() //只要存储了一个session,就会自动在redis中添加一个键值对,键是存储在浏览器中的key+value一起组成,相当于cookie,redis的值就是session设置的值,如ctx.session.name='fhx',则值为{...name:'fhx'}
}))
可以打开客户端程序,该程序可以查看存储的数据
重启一个命令行窗口
redis-cli
keys * //获取所有数据的key值
get key //获取对应key的value值
- 不一定需要session直接对redis进行操作,也可以自定义设置redis
const Redis = require('redis')
// 创建redis客户端
const Store = new Redis().client
Store.hset('fix','name',Math.random()) //在redis存储数据
命令行中
hget fix name //获取值
# Nuxt.js
+ ```
集成
vue2
vue Router //不用配
vuex
vue server renderer
vue-meta
工作流
1、Incoming Request指的是浏览器发出一个请求,那么服务端接收到这个请求之后呢
2、它要检查当前有没有nuxtServerInit这个配置项,如果有的话就先执行这个函数。Store action是用来操作vuex的
3、middleware中间件,这个中间件是和路由相关,在这里可以做任何你想要的功能
4、验证:validate(),可以配合高级动态路由去做验证,比如说这个页面是否允许跳到别的页面上去,如果没有得到我的校验的话,我可以跳走之类的等等
5、获取数据,又分两个函数,第一个是aysncData(),第二个是fetch(),他们两个实现的是同样的功能,都是获取数据,区别是aysncData()获取的数据是渲染vue组件的,fetch通常是修改vuex的也就是store这些东西的,
6、Render:渲染,有模板,有数据进行渲染了
7、其中有一个nuxt-link,如果是发起一个新的路由,那么这个时候要从头开始循环
安装vue init nuxt-community/koa-template
async mounted() {
let self = this
let {
status, data: {
list}} = await axios.get('/city/list')
console.log(list)
if (status === 200) {
self.list = list
}
}
//浏览器端渲染
async asyncData() {
let {
status, data: {
list}} = await axios.get('http://localhost:3000/city/list')
console.log(list)
if (status === 200) {
return {
list
}
}
}
//服务端渲染
服务器端编译好的内容下发给浏览器
异步获取到的数据同时给浏览器端(在浏览器端中创建一个scrip标签,把数据挂载到window对象中,到达了浏览器数据与浏览器同步)
其他安装 npm i -g npx npx create-nuxt-app project-name
npm i sass-loader node-sass -S 更改每个组件的lang='scss'
解决koa中模块化以CommonJs为主,该es6模块化 npm i babel-cli babel-preset-es2015 在dev和build后面添加 --exec babel-node
服务端
passport
// 提供了一个用户鉴权的框架,并把鉴权得到的用户身份供后续的业务逻辑来使用
import passport from 'koa-passport'
// 提供本地鉴权的代码框架
import LocalStrategy from 'passport-local'
import UserModel from '../../dbs/models/users'
// 为passport新增一个可用的策略
// 鉴权的作用有两个
// 1、鉴权失败可用拒绝用户访问
// 2、鉴权成功会把用户记录到context
// passport支持同时使用多个策略,它会从头开始尝试各个策略,直到
// 有一个策略做出处理或已尝试所有策略为止
// passport默认会使用session
// 会自动从请求中获取username,password两个字段,然后提供给用户自定义的函数进行鉴权
passport.use(new LocalStrategy(async function(username, password, done){
let where = {
username
}
let result = await UserModel.findOne(where)
if(result != null){
if(result.password === password){
return done(null, result)
}else{
return done(null, false, '密码错误')
}
}else{
return done(null, false, '用户不存在')
}
}))
passport.serializeUser(function(user,done){
// 是将信息存入到session
// ctx.login(id) 函数调用时触发,其中的参数会传给serializeUser函数作为第一个参数
// 序列化ctx.login()触发,就可以调用ctx.state.user
done(null, user)
})
// 反序列化(请求时,session中存在"passport":{"user":"1"}触发)
passport.deserialzeUser(function(user,done){
// 将信息从session中取出来
return done(null,user)
})
export default passport
// 服务端的入口文件 index.js
app.use(passport.initialize())
app.use(passport.session())
ctx.state.user 认证用户
ctx.login(user) 登录用户(序列化用户)
ctx.isAuthenticated() 判断是否认证
邮箱验证
import nodeMailer from 'nodemailer'
let username = ctx.request.body.username
const saveExpire = await Store.hget(`nodemail:${
username}`, 'expire')
// 验证时redis中没有saveExpire,有则说明在1分钟之内连续操作
if(saveExpire && new Date().getTime()-saveExpire<0){
ctx.body = {
code: -1,
msg: '验证请求过于频繁,1分钟1次'
}
return false
}
//定义后台管理员(发送对象)的信息
let transporter = nodemailer.createTransport({
host: Email.smtp.host,
port: 587,
secure: false, //true监听465端口,false监听其他端口
//配置的管理员的信息,如管理员的邮箱,如第三方授权信息
auth: {
user: Email.smtp.user,
pass: Email.smtp.pass
}
})
// 配置发送验证码相关信息(用户)
let ko = {
code: Email.smtp.code(), //向用户邮箱发送的验证码
expire: Email.smtp.expire(),
email: ctx.request.body.email,
user: ctx.request.body.username //给你个注册用户名发送验证码,发送验证码要有名字
}
// 邮件中要显示什么内容,这个也要定义
let mailOption = {
from: `"认证邮件"<${
Email.smtp.user}>`, //告诉收件方,谁给收件方发的
to: ko.email, //接收方
subject: '《高仿美团网全栈实战》 注册验证码 ', //邮件主题
html: `或许前路永夜,即便如此我也要前进,因为星光即便微弱也会为我照亮前路 您的邀请码${
ko.code}`
}
// 发送
await transporter.sendMail(mailOption, (error, info) => {
if(error){
return console.log('error')
}else{
// 验证码发送成功了,则存储验证码等相关信息,等用户点击注册时,提交的验证码与
// 在redis保存的验证码进行验证
// hmset 可以在redis存储多个键值对,获取对应的一个键值对,hget('key')
// HMSET myhash field1 "Hello" field2 "World"
// HGET myhash field1
Store.hmset(`nodemail:${
username}`,'code', ko.code, 'expire', ko.expire, 'email', ko.email)
}
})
ctx.body = {
code: 0,
msg: '验证码已发送,可能会有延时,有效期为1个小时'
}
数据库导入
mongoimport -d dbs `数据库` -c test `数据结合` pois.dat `数据源`
小点
汉字转字母
npm i js-pinyin
p = pinyinJS.getFullChars(汉字).toLocaleLowerCase().slice(0,1)
c = p.CharCodeAt(0) //方法可返回指定位置的字符的 Unicode 编码。这个返回值是 0 - 65535 之间的整数。
Object.entries(对象) //跟for in类似,区别在于不循环对象上的原型链
Object.sort((a,b) => return 大于0||小于0||等于0) //大于0,说明a比b大,a排在b后面,降序,小于0,升序
注意
浏览器post向服务器请求数据,数据不会encodeURIComponent,需要加这个。
get请求的数据,会编码,不需要加encodeURIComponent
边栏推荐
猜你喜欢
随机推荐
Bash shell位置参数
为android系统添加产品的过程
7. How to add the Click to RecyclerView and LongClick events
checkPermissions Missing write access to /usr/local/lib
再见篇:App专项技术优化
使用预训练语言模型进行文本生成的常用微调策略
It is not allowed to subscribe with a(n) xxx multiple times.Please create a fresh instance of xxx
自定义圆形seekBar,超简单
DP1101兼容CC1101是SUB1GHz无线收发芯片应用于智能家居
Cannot figure out how to save this field into database. You can consider adding a type converter for
【我的电赛日记(二)】ADF4351锁相环模块
FP5207电池升压 5V9V12V24V36V42V大功率方案
基于51单片机和物联网的智能家居系统(ESP8266物联网模块)
The overlapping effect of the two surfaceviews is similar to the video and handout practice in the live effect
DP4056电源保护芯片锂电池pin对pinTP4056
boost库智能指针
FP6296锂电池升压 5V9V12V内置 MOS 大功率方案原理图
国内IT市场还有发展吗?有哪些创新好用的IT运维工具可以推荐?
LLVM系列第二十八章:写一个JIT Hello World
The Handler you really understand?