基于Chrome V8引擎的JavaScript运行时
- V8是chrome的js引擎,以速度著称
- 运行时:代码的运行环境
- 之前只有浏览器能运行js
安装node
- nodejs.cn
- msi
- node -v
npm
- node package manage nodejs软件包管理工具
- npmjs.com
- 会随着nodejs一起被安装
- npm init 生成package.json其中包括项目所有依赖
nodemon
- 当检测到目录中的文件更改时,它会自动重启node应用程序。
- npm i nodemon --save-dev
- 使用了nodemon 就可以使用npm run dev ,只有node,使用node xx.js
common.js ES6模块化
注意导出用{},导入也要用{}接收
const sum =required(./地址)//多个用大括号
module.exports={
sum,text}
区别
这个会报错,ES Module必须放在最外层
nodejs debug
node处理http
Get请求
- 引入queryString
- queryString.parse(str)产生一个包含键值对的对象
Post请求体通过流的形式
Koa2 框架
- 安装脚手架 npm i -g koa-generator //-g全局安装
- 查看是否安装成功 koa2 --version
- cd到文件夹在命令行输入koa2
- 在命令行输入npm i / npm run start
- 访问http://localhost:3000/
- app.use(...)里都是中间件
- 每个中间件都是async函数
写一个接口(动态参数)
- 在routes文件夹下新建js文件
const router = require('koa-router')()
router,prefix('/api')
router.get('/json', async (ctx) => {
ctx.body = 'api list'
})
//ctx是res,rep的集合。ctx.query可以获取到queryString/ctx.request.body获取请求体
router.get('/:id',loginCheck,async function (ctx,next){
const id = ctx.params.id
const address = await getAddressById(id)
ctx.body = new SuccessModel(address)
})
module.exports = router
//数据库里tabs:[all,a,b,c] in里面的内容表示tabs属性要包含all
const list =await Product.find({
shopId,tabs:{
$in:all
}}).sort( _id:-1)
//数据库里_id是一个字符串,in里是一个数组,表示_id在这个ids数组中就能被找到
const list =await Product.find({
shopId,_id:{
$in:ids
}})
- 在app.js里引入,注册
const index = require('./routes/index')
app.use(index.routes(), index.allowedMethods())
svg验证码
ctx.body = svgCaptcha.create({
size:5,
ignoreChars:'0olil',
color:true,
noise:3
}).data
邮箱nodemailer
npm i nodemailer -S
配置文件
module.exports = {
host: 'smtp.qq.com',
port: 465,
secure: true,
auth: {
user: '2252647301@qq.com',
pass: 'aptwbjjnhvlqdjjg'
}
};
在route里引入使用
const nodemailer = require('nodemailer');
const config = require('../mailconfig.js');
router.get('/string', async (ctx, next) => {
const mailOptions = {
from: '2252647301@qq.com',
to: '2252647301@qq.com',
subject: 'Test email',
text: 'This is a test email',
html: `<title>HTML email</title>`
};
const transporter = nodemailer.createTransport(config);
try {
const info = await transporter.sendMail(mailOptions);
console.log('Email sent: ' + info.response);
ctx.body = {
success: true };
} catch (error) {
console.log(error);
ctx.body = {
success: false };
}
})
后续要封装成方法
密码加密
//封装成一个加密方法
const crypto=require('crypto')
module.exports = str=> crypto.createHash('md5').update(str).digest('hex')
password: {
type:String,
required:true,
set:value=>md5(value),
select:false//以后都不会返回密码
}//这样存入数据库的技术加密后的密码
中间件
app.use(async (ctx, next) => {
const start = new Date()
await next()//只有await执行完之后才能执行之后的代码,next()表示执行下一个中间件
const ms = new Date() - start
console.log(`${
ctx.method} ${
ctx.url} - ${
ms}ms`)
})
//多个中间件(p1,p2),按顺序执行next之前的代码,之后回过头来执行p2里next后的方法,p1里的next之后的方法
MongoDB
- mongodb.com production 社区服务 msi
- 接受条框后点Custom
- 不要勾选MongoDB compass
- 如果失败重新安装
- 如果弹出错误忽略
- 查看安装的MongoDB文件夹是是否有data log文件夹没有就新建,在data里新建db文件夹,在log里新建mongod.log
- 在bin文件夹下打开控制台输入启动mongo//mongodb.exe可关,mongod.exe不能关
- 图形界面,在官网sofeware下载compass 打开点击connect
- 如果连接失败,把data里的db里的mongod.lock删除,重新启动
使用compass
collect约等于表,document约等于表里的一项数据 - create database
- create collection
- 查询
- 排序 1正序 -1逆序
MongoDB连接nodejs
- 安装npm i mongodb --save
// nodejs 连接 mongodb
// 体会 nodejs 连接 mongodb 的能力,不会真正的用到路由上
// mongoose 对接路由的功能
const MongoClient = require('mongodb').MongoClient
const url = 'mongodb://localhost:27017' // 本地启动的 mongodb 服务
const dbName = 'comment1' // 数据库(留言板项目的数据库 )
MongoClient.connect(url, {
useUnifiedTopology: true,
useNewUrlParser: true
}, (err, client) => {
if (err) {
console.error('mongodb 连接出错', err)
return
}
console.log('mongodb 连接成功')
// 切换数据库 database
const db = client.db(dbName)
// 切换到指定的集合 collection
const userCollection = db.collection('users')
// // 查询数据
// userCollection.find().sort({ _id: -1 }).toArray((err, result) => {
// if (err) {
// console.error('查询数据出错', err)
// return
// }
// console.log('查询结果', result)
// })
// // 新增数据
// userCollection.insertOne({
// username: 'shuangyue',
// password: 'abc',
// age: 30,
// city: 'beijing'
// }, (err, result) => {
// if (err) {
// console.error('插入数据出错', err)
// return
// }
// console.log('插入后的返回结果', result.insertedCount, result.insertedId)//插入数量,插入的数据id
// })
// // 修改数据
// userCollection.updateOne(
// { username: 'zhangsan' }, // 修改的条件
// { $set: { age: 21 , city: 'beijing'} }, // 修改的内容
// (err, result) => {
// if (err) {
// console.error('修改数据出错', err)
// return
// }
// console.log('修改后的返回结果', result.modifiedCount)
// }
// )
// 删除数据
userCollection.deleteOne({
username: 'wangwu' }, (err, result) => {
if (err) {
console.error('删除数据出错', err)
return
}
console.log('删除成功')
})
// 关闭
// client.close()
})
规范连接 mongoose
- 在文件夹路径上唤出控制台,输入npm i mongoose --save
- 新建文件夹,新建js文件
- 一定要先启动mongod.exe
db.js
// 连接数据库(mongodb 的服务端)
const mongoose = require('mongoose')
const url = 'mongodb://localhost:27017'
const dbName = 'comment2'
mongoose.set('useCreateIndex', true)
mongoose.set('useFindAndModify', true)
// 开始连接
mongoose.connect(`${
url}/${
dbName}`, {
useNewUrlParser: true,
useUnifiedTopology: true
})
const conn = mongoose.connection
conn.on('error', err => {
console.error('mongoose 连接出错', err)
})
module.exports = mongoose
创建schema,定义了model会自动创建collection加一个s
model.js
// 数据模型(规范数据格式)
const mongoose = require('./db')
// 定义 User Schema (数据规范)
const UserSchema = mongoose.Schema({
username: {
type: String,
required: true, // 必需
unique: true // 唯一,不重复
},
password: String,
age: Number,
city: String,
// 性别
gender: {
type: Number,
default: 0 // 0 - 保密,1 男,2 女
}
}, {
timestamps: true // 时间戳,自动添加文档的创建时间、更新时间
})
// 定义 User Model
const User = mongoose.model('user', UserSchema)
// 定义 Comment Schema
const CommentSchema = mongoose.Schema({
content: {
type: String,
required: true // 必需
},
username: String // 用户名
}, {
timestamps: true })
// 定义 Comment Model
const Comment = mongoose.model('comment', CommentSchema)
module.exports = {
User,
Comment
}
新建文件夹查询新增
// 使用 model 操作数据
const {
User } = require('./model')
// 定义一个 async 的匿名函数,并执行。为了里面能用 await
!(async () => {
// // 新增数据 - 1
// const zhangsan = new User({
// username: 'zhangsan',
// password: 'abc',
// age: 20,
// city: 'beijing',
// gender: 1
// })
// zhangsan.save()
// // 新增数据 - 2
// const lisi = await User.create({
// username: 'lisi',
// password: '123',
// age: 23,
// city: 'shanghai'
// })
// console.log('lisi 创建完成', lisi)
// // 查询列表数据,返回的是数组
// const userList = await User.find({ username: 'zhangsan' })
// const userList = await User.find().sort({ _id: -1 })
// console.log('userList 查询结果', userList)
// 查询单条数据,返回的对象
const user = await User.findOne({
username: 'zhang' })
console.log('user 查询结果', user)
})()
新建文件夹更新删除
// 使用 model 操作数据
const {
User } = require('./model')
// 定义一个 async 的匿名函数,并执行。为了里面能用 await
!(async () => {
// // 更新
// const updateResult = await User.findOneAndUpdate(
// { username: 'zhangsan' }, // 条件
// { age: 30 }, // 更新的内容
// {
// new: true // 返回更新后的数据
// }
// )
// console.log('更新的返回结果', updateResult)
// // 删除
// const removeResult = await User.remove({ username: 'lisi' })
// console.log('删除的返回结果', removeResult)
})()
session cookie
cookie
在koa2使用cookie
session是在服务端存储的用户信息
koa2使用session,解决跨域
- npm i koa-generic-session --save// npm i koa2-cors --save
- 通过ctx.session使用session
- 在appjs写
const session = require('koa-generic-session')
const cors = require('koa2-cors')
//cors配置
app.use(cors({
origin: 'http://localhost:8080',//前端origin
credentials:true //允许跨域带cookie
}))
//session配置
app.keys = ['wertwe^&&*UUI123123'] // 秘钥
// 自定配置了 cookie 和 session
app.use(session({
// 配置 cookie
cookie: {
path: '/', // cookie 在根目录下有效
httpOnly: true, // cookie 只允许服务端来操作
maxAge: 24 * 60 * 60 * 1000 // cookie 的过期时间
}
}))
- 在controller层设置session ctx.session.userInfo={username}
- 使用session的数据 const username = ctx.session.userInfo.username
开发流程
数据库
- mongodb创建数据库和集合
- 使用mongoose定义schema和model
规范目录
新建文件夹 - 移动之后在bin-www修改app require('../src/app')
统一返回类
成功
失败class SuccessModel{ constructor(data){ this.errno = 0 if(data!=null){ this.data=data } } } module.exports = SuccessModel
如何使用class ErrorModel{ constructor(errno=-1,message='error'){ this.errno = errno this.message=message } } module.exports = ErrorModel
ctx.body = new SuccessModel(data)
ctx.body = new ErrorModel(10001,`注册失败 - ${
ex.message}`)
登录验证中间件
router.get('/:id',loginCheck,async function (ctx,next)//loginCheck是中间件,使用前需要require。如果没登陆,不允许访问
Redis
- GUI Another Redis Desktop Manager
- 执行redis-server.exe redis.windows.conf
- 创建一个新cmd,执行redis-cli.exe -h 127.0.0.1 -p 6379
- 一般redis有一个数据库DB0,但也支持多个数据库例如select 12
cli命令
# 五大常见的数据类型之 String
# 五大常见的数据类型之 Hash
# 五大常见的数据类型之 List
# 五大常见的数据类型之 Set
# 五大常见的数据类型之 Zset
发布订阅
subscribe zhang fang 监听多个管道
publish zhang "hello" 发送信息