刚刚, 我们运行了模板, 看到了界面, 那为什么我们没有后端项目这个模板就能直接运行呢?
因为其内部使用了mock.js虚拟了接口
那么首先, 我们要先了解一下刚刚下载的模板的模拟登录过程.
一. 理解原模板的mock模拟数据登录过程
1. 表单提交登录请求
首先,我们看 src\pages\login\Login.vue
, 看我们点击登录时发生了什么:
我们发现点击登录时,表单提交触发onSubmit方法
我们来看一下 onSubmit方法:
可以看到,第7步中调用了login方法. 我们看一下这个方法从哪引入的?
发现是 @/services/user
这可以很好理解, 登录是一个服务, 在网站设计中,我们往往把页面文件和服务文件(API文件) 一 一对应
下面, 我们来看一看login函数
2. 服务login函数
可以看到login里面只是进行了一个封装好的request请求, 没什么特别的
我们注意到请求中的一个参数 LOGIN, 他在@/services/api
里, 我们去看一下.
3. services/api
可以看到, 此文件非常简单, 目前只有LOGIN ROUTES两个url .同时写好了将来跨域要用的代码, 将来取消注释即可.
这里我们注意到BASE_URL是 process.env.VUE_APP_API_BASE_URL
我们去找这个全局变量
在工程根目录下找到 两个文件.env
和.env.development
, 我们可以把他们简单的理解为"生产环境"和"开发环境"
当然, 根据配置, 我们现在是开发环境 ,所以我们的请求是:http://dev.iczer.com/login
4. MOCK模拟接口
事实上, 当我们点击登录后, 系统并没有真的去请求这个地址, 根本就没有发送真的请求
而是被mock接管:
我们来看 src\mock\user\login.js
看到这里我们明白了:
mock返回数据给service
↓
service返回数据给前端
↓
前端收到数据后进行后续处理
我们就知道了, 如果我们自己写后端, 也应该这么返回数据
5. 后续处理 .then(this.afterLogin)
我们看看前端获取到数据后做了什么
我们注意到:第7步 获取路由配置时, 又进行了一个请求, 我们按照上面的方法分析就可以找到他的MOCK源.
这是vue-antd-admin的一个动态路由功能,需要配置, 这个日后再实验
二. 使用KOA2编写后端接口代替MOCK
完成了上面的分析后, 我们现在开始尝试用一个后端程序代替mock
1.新建koa2工程
koa2 vue-antd-admin-back
然后初始化工程
npm i
然后运行工程
npm run dev
访问 : http://127.0.0.1:3000/ 已经可以了
2. 解决跨域问题
参考文章: https://www.jianshu.com/p/6009513b931e
安装koa2-cors
npm i koa2-cors --save
然后在app.js中:
const cors = require('koa2-cors');
app.use(
cors({
origin: function(ctx) { //设置允许来自指定域名请求
if (ctx.url === '/test') {
return '*'; // 允许来自所有域名请求
}
return '*'; //只允许http://localhost:8080这个域名的请求
},
maxAge: 5, //指定本次预检请求的有效期,单位为秒。
credentials: true, //是否允许发送Cookie
allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], //设置所允许的HTTP请求方法'
allowHeaders: ['Content-Type', 'Authorization', 'Accept'], //设置服务器支持的所有头信息字段
exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'] //设置获取其他自定义字段
})
);
3. 前端项目配置环境
将 .env.development
内的base_url修改为: http://127.0.0.1:3000/
将 src\services\api.js
内的跨域代理打开, 把代理设置为http://localhost:3000, 同时,为了URL和文件的统一, 我把LOGIN的url改为了${BASE_URL}/user/login
现在,我们已经能看到请求了
这里,我们看到两个请求, 第一个是OPTIONS请求,用来探测服务器连接是否正常, 第二个才是真正的POST请求
在后端也可以收到了请求
接下来, 我们按照MOCK的格式进行响应就可以了
4. KOA2响应登录POST请求
我们看到, 前端post请求发送到 http://localhost:3000/user/login
所以, 我们应该响应此请求
具体操作:
- 我们新建
routes\user.js
文件
在里面写入post响应
const router = require('koa-router')()
router.prefix('/user')
router.post('/login', function (ctx, next) {
ctx.body = '这里写响应,一会儿再写'
})
module.exports = router
- 在app.js中引入这个route
const user = require('./routes/user')
app.use(user.routes(), user.allowedMethods())
- 下面,我们来具体写这个响应, 参考mock写就可以
具体参考第一节第4点
const router = require('koa-router')()
router.prefix('/user')
router.post('/login', function (ctx, next) {
let result = {}
const name = ctx.request.body.name
const password = ctx.request.body.password
console.log(ctx.request.body);
console.log(name);
console.log(typeof (name));
console.log(password);
console.log(typeof (password));
if (name !== 'admin' || password !== '888888') {
result.code = -1
result.message = '账户名或密码错误(admin/888888)'
} else {
result.code = 0
console.log(typeof (result.code));
result.message = '上午好' + ',欢迎回来'
console.log(typeof (result.message));
result.data = {}
result.data.user = {
name: '熊爸',
avatar: 'https://gw.alipayobjects.com/zos/rmsportal/WhxKECPNujWoWEFNdnJE.png',
address: '泰安市',
position: {
CN: "社畜",
HK: "計算服務事業群",
US: "engineer"
}
}
console.log(typeof (result.data.user));
result.data.token = 'Authorization:' + Math.random()
console.log(typeof (result.data.token));
result.data.expireAt = new Date(new Date().getTime() + 30 * 60 * 1000)
console.log(typeof (result.data.expireAt));
result.data.permissions = [{ id: 'queryForm', operation: ['add', 'edit'] }]
console.log(typeof (result.data.permissions));
result.data.roles = [{ id: 'admin', operation: ['add', 'edit', 'delete'] }]
console.log(typeof (result.data.roles));
}
ctx.body = result
})
module.exports = router
现在,我们点击登录, 不出意外的失败了, 不用着急, 看一下请求
我们发现
我们的login的POST请求已经成功,而且得到了返回数据
但是根据之前的分析, login后会触发afterlogin, 发送一个http://localhost:3000/routes请求(参考第一节第5点), 但我们还没有处理这个get请求
5. 处理后续 http://localhost:3000/routes 的get请求
这个请求其实是用户登录后申请动态路由资源的请求, 但是, 前端项目默认并没有开启动态路由, 所以我们可以非常简单的就把它处理好(其实只需要返回一个返回码0)
新建routes\routes.js
const router = require('koa-router')()
router.prefix('/routes')
router.get('/', function (ctx, next) {
let result = {}
result.code = 0
data = {}
})
module.exports = router
在app.js中
const routes = require('./routes/routes')
app.use(routes.routes(), routes.allowedMethods())
再点击登录,就可以成功了
现在, 我们已经完成登录并跳转到 /dashboard/workplace
由于我使用的是极简模板, 所以跳转错了, 我们只需要src\pages\login\Login.vue
的afterLogin()
方法的路由跳转改掉就可以了
三. 动态路由
上面, 虽然我们完成了登录进程, 但我们并没有实现动态路由, 如果我们想实现动态路由可以参考以下文章:
https://iczer.gitee.io/vue-antd-admin-docs/advance/async.html
具体步骤:
1. 在 /config/config.js 文件中设置 asyncRoutes 的值为 true
2. 注册路由组件
我们要把 视图和路由 配置起来,来确保页面有办法被访问到, 确保路由能够获取到页面
所有这一切在/router/async/router.map.js
中实现
路由按照如下的格式来注册:
registerName: { //路由组件注册名称,唯一标识
path: 'path', //路由path,可缺省,默认取路由注册名称 registerName 的值
name: '演示页', //路由名称
redirect: '/login', //路由重定向
component: () => import('@/pages/demo'), //路由视图
icon: 'permission', //路由的菜单icon,会注入到路由元数据meta中
invisible: false, //是否隐藏菜单项,true 隐藏,false 不隐藏,会注入到路由元数据meta中。
authority: { //路由权限配置,会注入到路由元数据meta中。可缺省,默认为 ‘*’, 即无权限限制
permission: 'form', //路由需要的权限
role: 'admin' //路由需要的角色。当permission未设置,通过 role 检查权限
},
page: { //路由的页面数据,会注入到路由元数据meta中
title: '演示页', //页面标题
breadcrumb: ['首页', '演示页'] //页面面包屑
}
}
3. 配置基本路由
如果没有任何路由,你的应用是无法访问的,所以我们需要在本地配置一些基本的路由,比如登录页、404、403 等。你可以在 /router/async/config.async.js 文件中配置一些本地必要的路由。
这个基本不用动
4. 后端返回动态路由
我们要按照文档要求的格式返回路由请求 routes\routes.js
const router = require('koa-router')()
router.prefix('/routes')
router.get('/', function (ctx, next) {
let result = {}
result.code = 0
result.data = [
{
router: 'root',
children: [
{
router: 'demo',
path: 'demo',
name: '演示页',
icon: 'file-word',
authority: {role: 'admin'}
},
{
router: 'parent1',
children: ['exp404','exp403','exp500'],
},
]
}
]
ctx.body = result
})
module.exports = router