自己搭建了一个前后端的项目,基于目前项目组的开发框架,主要是实现了在node端如何生成一个接口,以及在前端项目如何调用
前端用的 vue + axios 后端用的 egg.js + sequelize
1. 建表
我用一个自己随便写的排行榜的表进行模拟,虽然是模拟,但是也要加上注释哦
CREATE TABLE `rank_list` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '排行内容' COLLATE 'utf8mb4_general_ci',
`created_at` INT(11) NOT NULL COMMENT '创建时间,unix时间戳,单位秒',
`sort` INT(11) NOT NULL DEFAULT '0' COMMENT '排行序号',
PRIMARY KEY (`id`) USING BTREE,
INDEX `created_at` (`created_at`) USING BTREE
)
COMMENT='排行榜单'
COLLATE='utf8mb4_general_ci'
ENGINE=InnoDB
;
我们可以看到在本地数据库有一个
下一步就是我如何将读到这个表里面的数据
2.node项目
2.1 创建node项目-egg-example
1用egg.js搭建初始项目
$ mkdir egg-example && cd egg-example
$ npm init egg --type=simple
$ npm i
npm run dev
一个node项目已经搭建好,用egg.js框架,因为orm会比sql更具有优势,写sql容易出错,可以简单的增删改查使用orm,但是复制的汇总等,可以使用sql,sql对于复杂的数据关系处理起来更加灵活. 推荐: SQL与ORM的优缺点
2下载sequelize orm框架
npm install --save egg-sequelize mysql2
因为使用egg.js里面的plugins是要手动引入的,所以在 config/plugin.js 中引入 egg-sequelize 插件
'use strict'
/** @type Egg.EggPlugin */
module.exports = {
// had enabled by egg
// static: {
// enable: true,
// }
sequelize: {
enable: true,
package: 'egg-sequelize',
},
}
2.2 配置config
在config底下建立一个新的文件,叫做config.local.js
config.local.js内容
'use strict'
const nowMode = 'local'
const mysqlConfigMap = {
local: {
username: 'xxx',
password: 'xxx',
host: '127.0.0.1',
port: xxx,
},
}
const dataBaseMap = {
local: {
database: 'test', // 就是你数据库里面的库名,我上面有截图那个test
},
}
const mysqlBaseConfig = {
dialect: 'mysql',
...mysqlConfigMap[nowMode],
timezone: '+08:00',
define: {
freezeTableName: true, // 防止修改表名为复数
underscored: true, // 防止驼峰式字段被默认转为下划线
},
}
module.exports = () => {
return {
// 数据库配置
sequelize: {
datasources: [{
delegate: 'model',
baseDir: 'model',
...dataBaseMap[nowMode],
...mysqlBaseConfig,
}],
},
}
}
如何配置可以看sequelize搜索关键词config
接下来我们就看看如何利用orm工具来读取表中的数据
2.3 在model中写入表中的数据
在app下级建立rankList文件,文件名和表名保持一致
这个 Model 就可以在 Controller 和 Service 中通过 app.model.XXX(xxx在这里为rank_list表)访问到,不懂得可以查看 sequelize搜索关键词model
'use strict'
/* 排行榜 */
module.exports = app => {
const { INTEGER, STRING } = app.Sequelize
const RankList = app.model.define('rank_list', {
id: {
type: INTEGER(11),
primaryKey: true,
autoIncrement: true,
comment: '主键',
},
name: {
type: STRING(50),
allowNull: false,
defaultValue: '',
comment: '排行内容',
},
sort: {
type: INTEGER(11),
allowNull: false,
defaultValue: 1,
comment: '排行序号',
},
createdAt: {
type: STRING(256),
allowNull: false,
defaultValue: '',
field: 'created_at',
comment: '创建时间',
},
})
return RankList
}
2.4 读取表中的数据,写接口
1.设置路由 找到app/router.js 'use strict';
/**
* @param {Egg.Application} app - egg application
*/
module.exports = app => {
const {
router,
controller: {
home,
rankList,
},
} = app
router.get('/', home.index)
router.get('/rankList', rankList.getRankingList)
}
相比初始页面,我多解构了controller这一个层级,上面的意思就是路由是/rankList(也就是以后前端需要访问的接口),rankList.getRankingList表示的是controller文件底下的rankList文件里面的getRankingList方法
2.在contorller文件底下建rankList文件,并且调用service数据
'use strict'
const baseController = require('./baseController')
class RankListController extends baseController {
async getRankingList() {
const data = await this.service.rankList.getRankingList()
this.success({ data })
}
}
module.exports = RankListController
因为抛出接口数据的success方法在controller里面都能用到,所以可以建立一个与rankList同级的baseController
baseController文件内容
'use strict'
const { Controller } = require('egg')
class BaseController extends Controller {
/**
* 公用返回成功结果的函数
* @param { Object } Object 成功结果数据
* @param { Number } Object.status http状态码
* @param { Number } Object.code 业务code 状态码
* @param { String } Object.msg 结果信息
* @param { any } Object.data 返回的数据
*/
success({ status = 200, code = 0, msg = 'success', data } = {}) {
this.ctx.body = {
code,
msg,
data,
}
this.ctx.status = status
}
}
module.exports = BaseController
一般来说前端只要判断code = 0 就表示成功,然后返回对应的数据格式
rankList文件内容
'use strict'
const baseController = require('./baseController')
class RankListController extends baseController {
async getRankingList() {
const data = await this.service.rankList.getRankingList()
this.success({ data })
}
}
module.exports = RankListController
这里RankListController已经不是继承父类Controller,而是继承baseController, Controller相当于RankListController的爷爷.
controller目前不直接从表里面获取数据,而是调用service,让service从表里面获取数据
3.service来获取表里面的数据 egg.js官网
要理解为什么要分为service和controller,可以查看官方文档
controller负责解析用户的输入,处理后返回相应的结果
service就是在复杂业务场景下用于做业务逻辑封装的一个抽象层,写sql,或者用orm处理数据,从表里面读取数据
service底下rankList内容
'use strict'
const Service = require('egg').Service
class rankListService extends Service {
/**
* 排行榜
*/
async getRankingList() {
const { rows, count } = await this.ctx.model.RankList.findAndCountAll({
attributes: { exclude: [ 'createdAt', 'updatedAt' ] },
})
return { list: rows, total: count }
}
}
module.exports = rankListService
2.5根据路由读取数据
3前端调用接口数据
3.1 用vue-cli创建一个前端vue项目
全局安装
npm install -g @vue/cli
创建项目project
vue create project
进入文件夹
cd project
运行
npm run serve
先安装axios
npm install axios --save
建立request文件以及api文件
request内容
import axios from 'axios'
var baseURL = 'http://127.0.0.1:7001'
const service = axios.create({
baseURL: baseURL,
timeout: 100000 // request timeout
})
service.interceptors.request.use(
config => {
return config
},
error => {
// do something with request error
console.log(error) // for debug
return Promise.reject(error)
}
)
// response interceptor
service.interceptors.response.use(
response => {
const res = response.data
// console.log('resp:')
// console.log(res)
// if the custom code is not 0, it is judged as an error.
if (res.code !== 0) {
alert('!==0')
return Promise.reject(res.message || 'error')
} else {
return res.data
}
},
error => {
console.log('err' + error) // for debug
let msg = error.message
console.log(msg);
return Promise.reject(error)
}
)
export default service
rankList api 内容
import request from '@/utils/request'
export function getRankList() {
return request({
url: '/rankList',
method: 'get',
})
}
3.2调用
template
<div style="border-top: 1px solid red">
<div v-for="(item, index) in rankList" :key="index">
序号: {{ item.sort }}
排行名: {{item.name}}
</div>
</div>
javascript
import { getRankList } from '@/api/rankList'
export default {
name: 'HelloWorld',
data() {
return {
rankList: [],
}
},
async created() {
const { list } = await getRankList()
this.rankList = list
console.log(this.rankList, 'this.rankList')
}
}
3.3显示效果
跨域了,这里应该在服务端设置一下跨域
1.先下载egg-cors
npm i egg-cors --save
2.在plugin里面配置,config.default.js配置
'use strict'
/** @type Egg.EggPlugin */
module.exports = {
// had enabled by egg
// static: {
// enable: true,
// }
sequelize: {
enable: true,
package: 'egg-sequelize',
},
cors: {
enable: true,
package: 'egg-cors',
},
}
config.default.js
config.cors = {
origin: '*',
allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH,OPTIONS',
};
3.运行
npm run dev
最终效果
欢迎大家一起交流,珍惜每一天,过好当下-_-