uni-app 25后端api开发和前后端交互(1-50)
Posted 2019ab
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uni-app 25后端api开发和前后端交互(1-50)相关的知识,希望对你有一定的参考价值。
1创建项目和基础配置
创建项目
安装egg.js
全局切换镜像:
npm config set registry https://registry.npm.taobao.org
我们推荐直接使用脚手架,只需几条简单指令,即可快速生成项目(npm >=6.1.0):
mkdir egg-example && cd egg-example
npm init egg --type=simple --registry https://registry.npm.taobao.org
npm i
启动项目:
npm run dev
open http://localhost:7001
关闭csrf开启跨域
安装
npm i egg-cors --save
配置插件
// {app_root}/config/plugin.js
cors:{
enable: true,
package: 'egg-cors',
},
config / config.default.js 目录下配置
config.security = {
// 关闭 csrf
csrf: {
enable: false,
},
// 跨域白名单
domainWhiteList: [ 'http://localhost:3000' ],
};
// 允许跨域的方法
config.cors = {
origin: '*',
allowMethods: 'GET, PUT, POST, DELETE, PATCH'
};
2全局抛出异常处理
// app/middleware/error_handler.js
module.exports = (option, app) => {
return async function errorHandler(ctx, next) {
try {
await next();
// 404 处理
if(ctx.status === 404 && !ctx.body){
ctx.body = {
msg:"fail",
data:'404 错误'
};
}
} catch (err) {
// 记录一条错误日志
app.emit('error', err, ctx);
const status = err.status || 500;
// 生产环境时 500 错误的详细错误内容不返回给客户端,因为可能包含敏感信息
const error = status === 500 && app.config.env === 'prod'
? 'Internal Server Error'
: err.message;
// 从 error 对象上读出各个属性,设置到响应中
ctx.body = {
msg:"fail",
data:error
};
ctx.status = status;
}
};
};
// config/config.default.js
config.middleware = ['errorHandler'];
3封装api返回格式扩展
// app/extend/context.js
module.exports = {
// 成功提示
apiSuccess(data = '', msg = 'ok', code = 200) {
this.body = { msg, data };
this.status = code;
},
// 失败提示
apiFail(data = '', msg = 'fail', code = 400) {
this.body = { msg, data };
this.status = code;
},
};
4sequelize数据库和迁移配置
数据库配置
安装并配置egg-sequelize插件(它会辅助我们将定义好的 Model 对象加载到 app 和 ctx 上)和mysql2模块:
npm install --save egg-sequelize mysql2
在config/plugin.js中引入 egg-sequelize 插件
exports.sequelize = {
enable: true,
package: 'egg-sequelize',
};
在config/config.default.js
config.sequelize = {
dialect: 'mysql',
host: '127.0.0.1',
username: 'root',
password: 'root',
port: 3306,
database: 'egg-wechat',
// 中国时区
timezone: '+08:00',
define: {
// 取消数据表名复数
freezeTableName: true,
// 自动写入时间戳 created_at updated_at
timestamps: true,
// 字段生成软删除时间戳 deleted_at
// paranoid: true,
createdAt: 'created_at',
updatedAt: 'updated_at',
// deletedAt: 'deleted_at',
// 所有驼峰命名格式化
underscored: true
}
};
迁移配置
sequelize 提供了sequelize-cli工具来实现Migrations,我们也可以在 egg 项目中引入 sequelize-cli。
npm install --save-dev sequelize-cli
egg 项目中,我们希望将所有数据库 Migrations 相关的内容都放在database目录下,所以我们在项目根目录下新建一个.sequelizerc配置文件:
'use strict';
const path = require('path');
module.exports = {
config: path.join(__dirname, 'database/config.json'),
'migrations-path': path.join(__dirname, 'database/migrations'),
'seeders-path': path.join(__dirname, 'database/seeders'),
'models-path': path.join(__dirname, 'app/model'),
};
初始化 Migrations 配置文件和目录
npx sequelize init:config
npx sequelize init:migrations
// npx sequelize init:models
行完后会生成database/config.json文件和database/migrations目录,我们修改一下database/config.json中的内容,将其改成我们项目中使用的数据库配置:
{
"development": {
"username": "root",
"password": null,
"database": "eggapi",
"host": "127.0.0.1",
"dialect": "mysql",
"timezone": "+08:00"
}
}
创建数据库
npx sequelize db:create
# 升级数据库
npx sequelize db:migrate
# 如果有问题需要回滚,可以通过 `db:migrate:undo` 回退一个变更
# npx sequelize db:migrate:undo
# 可以通过 `db:migrate:undo:all` 回退到初始状态
# npx sequelize db:migrate:undo:all
模型关联
User.associate = function(models) {
// 关联用户资料 一对一
User.hasOne(app.model.Userinfo);
// 反向一对一关联
// Userinfo.belongsTo(app.model.User);
// 一对多关联
User.hasMany(app.model.Post);
// 反向一对多关联
// Post.belongsTo(app.model.User);
// 多对多
// User.belongsToMany(Project, { as: 'Tasks', through: 'worker_tasks', foreignKey: 'userId' })
// 反向多对多
// Project.belongsToMany(User, { as: 'Workers', through: 'worker_tasks', foreignKey: 'projectId' })
}
5用户表设计和迁移
数据表设计和迁移
创建数据迁移表
npx sequelize migration:generate --name=user
1.执行完命令后,会在database / migrations / 目录下生成数据表迁移文件,然后定义
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
const { INTEGER, STRING, DATE, ENUM } = Sequelize;
// 创建表
await queryInterface.createTable('user', {
id: {
type: INTEGER(20).UNSIGNED,
primaryKey: true,
autoIncrement: true
},
username: {
type: STRING(30),
allowNull: false,
defaultValue: '',
comment: '用户名称',
unique: true
},
nickname: {
type: STRING(30),
allowNull: false,
defaultValue: '',
comment: '昵称',
},
email: {
type: STRING(160),
comment: '用户邮箱',
unique: true
},
password: {
type: STRING(200),
allowNull: false,
defaultValue: ''
},
avatar: {
type: STRING(200),
allowNull: true,
defaultValue: ''
},
phone: {
type: STRING(20),
comment: '用户手机',
unique: true
},
sex: {
type: ENUM,
values: ['男', '女', '保密'],
allowNull: true,
defaultValue: '男',
comment: '用户性别'
},
status: {
type: INTEGER(1),
allowNull: false,
defaultValue: 1,
comment: '状态'
},
sign: {
type: STRING(200),
allowNull: true,
defaultValue: '',
comment: '个性签名'
},
area: {
type: STRING(200),
allowNull: true,
defaultValue: '',
comment: '地区'
},
created_at: DATE,
updated_at: DATE
});
},
down: async queryInterface => {
await queryInterface.dropTable('user');
}
};
执行 migrate 进行数据库变更
npx sequelize db:migrate
6注册功能实现
新建user.js控制器
// app/controller/user.js
'use strict';
const Controller = require('egg').Controller;
class UserController extends Controller{
// 注册
async reg(){
let {ctx,app} = this;
// 参数验证
let {username,password,repassword} = this.ctx.request.body;
// 验证用户是否已存在
if(await app.model.User.findOne({
where:{
username
}
})){
ctx.throw(400,'用户名已存在');
}
// 创建用户
await app.model.User.create({
username,
password
})
if(!user){
ctx.throw(400,'创建用户失败');
}
ctx.apiSuccess(user);
// this.ctx.body ='注册';
}
}
module.exports = UserController;
新建user.js数据迁移文件
// app/model/user.js
'use strict';
module.exports = app => {
const { STRING, INTEGER, DATE, ENUM, TEXT } = app.Sequelize;
// 配置(重要:一定要配置详细,一定要!!!)
const User = app.model.define('user', {
id: {
type: INTEGER(20).UNSIGNED,
primaryKey: true,
autoIncrement: true
},
username: {
type: STRING(30),
allowNull: false,
defaultValue: '',
comment: '用户名称',
unique: true
},
nickname: {
type: STRING(30),
allowNull: false,
defaultValue: '',
comment: '昵称',
},
email: {
type: STRING(160),
comment: '用户邮箱',
unique: true
},
password: {
type: STRING(200),
allowNull: false,
defaultValue: ''
},
avatar: {
type: STRING(200),
allowNull: true,
defaultValue: ''
},
phone: {
type: STRING(20),
comment: '用户手机',
unique: true
},
sex: {
type: ENUM,
values: ['男', '女', '保密'],
allowNull: true,
defaultValue: '男',
comment: '用户性别'
},
status: {
type: INTEGER(1),
allowNull: false,
defaultValue: 1,
comment: '状态'
},
sign: {
type: STRING(200),
allowNull: true,
defaultValue: '',
comment: '个性签名'
},
area: {
type: STRING(200),
allowNull: true,
defaultValue: '',
comment: '地区'
},
created_at: DATE,
updated_at: DATE
});
return User;
};
注册路由
// 用户注册
router.post('/reg',controller.user.reg);
下图是我测试的截图
7参数验证功能实现(一)
参数验证
插件地址:
https://www.npmjs.com/package/egg-valparams
安装
npm i egg-valparams --save
配置
// config/plugin.js
valparams : {
enable : true,
package: 'egg-valparams'
},
// config/config.default.js
config.valparams = {
locale : 'zh-cn',
throwError: true
};
在控制器里使用
class XXXController extends app.Controller {
// ...
async XXX() {
const {ctx} = this;
ctx.validate({
system : {type: 'string', required: false, defValue: 'account', desc: '系统名称'},
token : {type: 'string', required: true, desc: 'token 验证'},
redirect: {type: 'string', required: false, desc: '登录跳转'}
});
// if (config.throwError === false)
if(ctx.paramErrors) {
// get error infos from `ctx.paramErrors`;
}
let params = ctx.params;
let {query, body} = ctx.request;
// ctx.params = validater.ret.params;
// ctx.request.query = validater.ret.query;
// ctx.request.body = validater.ret.body;
// ...
ctx.body = query;
}
// ...
}
// app/controller/user.js
'use strict';
const Controller = require('egg').Controller;
class UserController extends Controller{
// 注册
async reg(){
let {ctx,app} = this;
// 参数验证
ctx.validate({
username:{type: 'string', required: true,range:{min:10,max:20},desc: '用户名'},
password:{type: 'string', required: true, desc: '密码'},
repassword:{type: 'string', required: true, desc: '确认密码'}
},{
equals:[
['password','repassword']
]
});
let {username,password,repassword} = this.ctx.request.body;
// 验证用户是否已存在
if(await app.model.User.findOne({
where:{
username
}
})){
ctx.throw(400,'用户名已存在');
}
// 创建用户
await app.model.User.create({
username,
password
}以上是关于uni-app 25后端api开发和前后端交互(1-50)的主要内容,如果未能解决你的问题,请参考以下文章