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