2022年最新《谷粒学院开发教程》:2 - 前后端交互篇
资料 |
---|
资料地址 |
后台管理系统目录 | 前台展示系统目录 |
---|---|
1 - 构建工程篇 | 7 - 渲染前台篇 |
2 - 前后交互篇 | 8 - 前台登录篇 |
3 - 文件上传篇 | 9 - 前台课程篇 |
4 - 课程管理篇 | 10 - 前台支付篇 |
5 - 章节管理篇 | 11 - 统计分析篇 |
6 - 微服务治理 | 12 - 项目完结篇 |
目录
- 一、搭建前端工程
- 1.1、测试启动
- 1.2、目录结构
- 1.3、配置环境
- 二、后台系统登录功能
- 2.1、分析登录流程代码
- 2.2、编写接口
- 三、讲师模块的前端实现
- 3.1、路由视图及测试讲师列表接口
- 3.2、渲染讲师列表
- 3.3、分页功能实现
- 3.4、多条件查询功能
- 3.5、讲师删除
- 3.6、讲师添加
- 3.7、讲师修改-回显数据
- 3.8、讲师修改
- 3.9、bug解决
一、搭建前端工程
1.1、测试启动
1、从资料中解压 vue-element-admin
修改为 gulicollege_ui
2、安装依赖 npm install
(安装太慢了直接放弃)
2、从资料中拷贝 node_modules
文件夹到项目中 并执行如下安装依赖
npm install node-sassnpm i node-sass -Dnpm install --save element-ui
3、启动 npm run dev
1.2、目录结构
.
├── build // 构建脚本
├── config // 全局配置
├── node_modules // 项目依赖模块
├── src //项目源代码
├── static // 静态资源
└── package.jspon // 项目信息和依赖配置
src
├── api // 各种接口
├── assets // 图片等资源
├── components // 各种公共组件,非公共组件在各自view下维护
├── icons //svg icon
├── router // 路由表
├── store // 存储
├── styles // 各种样式
├── utils // 公共工具,非公共工具,在各自view下维护
├── views // 各种layout
├── App.vue //***项目顶层组件***
├── main.js //***项目入口文件***
└── permission.js //认证入口
1.3、配置环境
1、package.json
{"name": "gulicollege_ui","version": "3.8.0","license": "MIT","description": "谷粒学院后台管理系统","author": "Laptoy",
}
2、config/index.js 配置端口号
port: 9528
3、config/index.js 关闭语法检查
useEslint: false
4、config/dev.env.js
修改为访问后台端口
BASE_API: '"http://localhost:8001"',
二、后台系统登录功能
2.1、分析登录流程代码
1、src/views/login/index.vue
methods: {handleLogin() {this.$refs.loginForm.validate(valid => {if (valid) {this.loading = true// 触发 store 的 Login事件this.$store.dispatch('Login', this.loginForm).then(() => {this.loading = falsethis.$router.push({ path: this.redirect || '/' })}).catch(() => {this.loading = false})} else {console.log('error submit!!')return false}})}
}
2、src/store/modules/user.js
(这里没有使用 namespaces: true
) 所以不需要通过命名空间调用
import { login, logout, getInfo } from '@/api/login'actions: {// 登录Login({ commit }, userInfo) {const username = userInfo.username.trim()return new Promise((resolve, reject) => {login(username, userInfo.password).then(response => {const data = response.datasetToken(data.token)commit('SET_TOKEN', data.token)resolve()}).catch(error => {reject(error)})})},
}
3、src/api/login.js
(通过 axios 发送请求)
import request from '@/utils/request'export function login(username, password) {return request({url: '/user/login',method: 'post',data: {username,password}})
}
4、src/utils/request.js
(封装 axios 调用)
import axios from 'axios'
import { Message, MessageBox } from 'element-ui'
import store from '../store'
import { getToken } from '@/utils/auth'// 创建axios实例
const service = axios.create({baseURL: process.env.BASE_API, // api 的 base_urltimeout: 5000 // 请求超时时间
})// request拦截器
service.interceptors.request.use(config => {if (store.getters.token) {config.headers['X-Token'] = getToken() // 让每个请求携带自定义token 请根据实际情况自行修改}return config},error => {// Do something with request errorconsole.log(error) // for debugPromise.reject(error)}
)// response 拦截器
service.interceptors.response.use(response => {/*** code为非20000是抛错 可结合自己业务进行修改*/const res = response.dataif (res.code !== 20000) {Message({message: res.message,type: 'error',duration: 5 * 1000})// 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了;if (res.code === 50008 || res.code === 50012 || res.code === 50014) {MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录','确定登出',{confirmButtonText: '重新登录',cancelButtonText: '取消',type: 'warning'}).then(() => {store.dispatch('FedLogOut').then(() => {location.reload() // 为了重新实例化vue-router对象 避免bug})})}return Promise.reject('error')} else {return response.data}},error => {console.log('err' + error) // for debugMessage({message: error.message,type: 'error',duration: 5 * 1000})return Promise.reject(error)}
)export default service
2.2、编写接口
根据前端代码分析
1、登录请求需要返回 token
2、获取用户信息请求需要返回 roles、name、avatar
1、EduLoginController (使用 @CrossOrigin 解决跨域问题)
@Api(tags = "登录模块")
@RestController
@CrossOrigin //解决跨域问题
@RequestMapping("/eduservice/user")
public class EduLoginController {// 登录@PostMapping("/login")public R login() {return R.ok().data("token", "admin");}// 获取信息@GetMapping("/info")public R info() {return R.ok().data("roles", "admin").data("name", "Laptoy").data("avatar", "https://img-blog.csdnimg.cn/480b7a82bddb4f6a9b6942c88db18d85.png");}// 登出@PostMapping("/logout")public R logOut() {return R.ok();}
}
2、修改 src/api/login.js
匹配后端接口
三、讲师模块的前端实现
3.1、路由视图及测试讲师列表接口
1、添加路由 - src/router/index.js
// 讲师模块路由
{path: '/teacher',component: Layout,redirect: '/teacher/table',name: '讲师管理',meta: { title: '讲师管理', icon: 'example' },children: [{path: 'table',name: '讲师列表',component: () => import('@/views/edu/teacher/list.vue'),meta: { title: '讲师列表', icon: 'table' }},{path: 'save',name: '添加讲师',component: () => import('@/views/edu/teacher/save.vue'),meta: { title: '添加讲师', icon: 'tree' }}]
},
2、创建路由对应组件
- 创建文件夹
src/views/edu/teacher
- 创建
list.vue
和save.vue
组件
3、定义访问的接口地址
在src/api文件创建 teacher/teacher.js
定义访问的接口地址
import request from '@/utils/request'export default {// 1、获取讲师列表(多条件分页查询)getTeacherListPage(page, limit, teacherQuery) {return request({url: `/eduservice/teacher/pageTeacherCondition/${page}/${limit}`,method: 'post',data: teacherQuery})}
}
4、组件页面调用定义接口方法 - list.vue
<template><div class="app-container">讲师列表</div>
</template><script>
import teacher from '@/api/teacher/teacher.js'export default {data() {return {list: null, // 查询之后给接口返回的数据装的集合page: 1, // 当前页limit: 5, // 每页显示记录数teacherQuery: {}, // 条件封装对象total: 0 // 总记录数}},created() {this.getList()},methods: {// 获取讲师列表getList() {teacher.getTeacherListPage(this.page, this.limit, this.teacherQuery).then((resp) => {this.list = resp.data.dataconsole.log(this.list)this.total = resp.data.totalconsole.log(this.total)}).catch((err) => {console.log(err)})}}
}
</script>
5、测试
3.2、渲染讲师列表
1、ui
<template><div><el-table :data="list" style="width: 100%" border fit highlight-current-row element-loading-text="数据加载中"><el-table-column prop="date" label="序号" width="70" align="center"><template slot-scope="scope">{{ (page - 1) * limit + scope.$index + 1 }}</template></el-table-column><el-table-column prop="name" label="名称" width="80" /><el-table-column label="头衔" width="80"><template slot-scope="scope">{{ scope.row.level === 1 ? "高级讲师" : "首席讲师" }}</template></el-table-column><el-table-column prop="intro" label="资历" /><el-table-column prop="gmtCreate" label="添加时间" width="160" /><el-table-column prop="sort" label="排序" width="60" /><el-table-column label="操作" width="200" align="center"><template slot-scope="scope"><router-link :to="'/edu/teacher/edit/' + scope.row.id"><el-button type="primary" size="mini" icon="el-icon-edit">修改</el-button></router-link><el-button type="danger" size="mini" icon="el-icon-delete" @click="removeDataById(scope.row.id)">删除</el-button></template></el-table-column></el-table></div>
</template>
2、展示
3.3、分页功能实现
1、ui
<div><el-table></el-table><el-pagination :total="total" :page-size="limit" :current-page="page" background layout="prev, pager, next,total,jumper" style="padding: 30px 0; text-align: center" @current-change="getList" />
</div>
2、方法
3、展示
3.4、多条件查询功能
1、ui
<!--多条件查询表单-->
<el-form :inline="true" class="demo-form-inline" style="margin-left: 20px; margin-top: 12px;"><el-form-item label="名称"><el-input v-model="teacherQuery.name" placeholder="请输入名称"></el-input></el-form-item><el-form-item label="级别"><el-select v-model="teacherQuery.level" placeholder="讲师头衔"><el-option label="高级讲师" :value="1"></el-option><el-option label="特级讲师" :value="2"></el-option></el-select></el-form-item><el-form-item label="添加时间"><el-time-picker placeholder="选择开始时间" v-model="teacherQuery.begin" value-format="yyyy-MM-dd HH:mm:ss" default-time="00:00:00" type="datetime"></el-time-picker</el-form-item><el-form-item><el-time-picker placeholder="选择截止时间" v-model="teacherQuery.end" value-format="yyyy-MM-dd HH:mm:ss" default-time="00:00:00" type="datetime"></el-time-picker></el-form-item><el-form-item><el-button type="primary" icon="el-icon-search" @click="getList()">查询</el-button><el-button type="default" @click="resetData()">清空</el-button></el-form-item>
</el-form>
2、方法
export default {methods: {// 清空查询栏resetData() {// 表单输入项数据清空this.teacherQuery = {};// 查询所有讲师数据this.getList();},}
}
3、展示
3.5、讲师删除
1、定义API - src/api/teacher/teacher.js
export default { ...// 2、根据id删除讲师removeById(id) {return request({url: `/eduservice/teacher/deleteTeacherById/${id}`,method: 'delete',})}
}
2、定义 methods
// 根据id删除讲师
removeDataById(id) {this.$confirm("此操作将永久删除该讲师记录, 是否继续?", "提示", {confirmButtonText: "确定",cancelButtonText: "取消",type: "warning",}).then(() => {teacher.removeById(id).then((resp) => {this.$message({type: "success",message: "删除成功!",});//刷新页面this.getList();});});
}
3.6、讲师添加
1、定义API
// 添加讲师
saveTeacher(teacher) {return request({url: `/eduservice/teacher/save`,method: `post`,data: teacher})
}
2、初始化 save.vue 组件
<template><div class="app-container"><el-form label-width="120px"><el-form-item label="讲师名称"><el-input v-model="teacher.name" /></el-form-item><el-form-item label="讲师排序"><el-input-number v-model="teacher.sort" controls-position="right" :min="0" /></el-form-item><el-form-item label="讲师头衔"><el-select v-model="teacher.level" clearable placeholder="选择讲师头衔"><el-option :value="1" label="高级讲师" /><el-option :value="2" label="首席讲师" /></el-select></el-form-item><el-form-item label="讲师资历"><el-input v-model="teacher.career" placeholder="职业生涯、获得的证书、其他含金量的经历" /></el-form-item><el-form-item label="讲师简介"><el-input v-model="teacher.intro" :rows="3" type="textarea" /></el-form-item><!-- 讲师头像:TODO --><el-form-item><el-button :disabled="saveBtnDisabled" type="primary" @click="saveOrUpdate">保存</el-button></el-form-item></el-form></div>
</template><script>
//引入对应的新增api方法
import teacherApi from "@/api/teacher/teacher.js";export default {data() {return {teacher: {name: "",sort: 0,level: 1,career: "",intro: "",avatar: "",},saveBtnDisabled: false, // 保存按钮是否禁用,};},methods: {saveOrUpdate() {this.saveBtnDisabled = true; // 防止表单多次提交,保存后就禁用按钮this.saveData();},// 保存saveData() {teacherApi.saveTeacher(this.teacher).then((resp) => {//添加成功//提示信息this.$message({message: "添加讲师记录成功",type: "success",});//回到讲师列表 路由跳转this.$router.push({ path: '/teacher/table' })});},},
};
</script>
3、展示
3.7、讲师修改-回显数据
1、添加路由 - 实际上以保存组件作为模板跳转
// 讲师模块路由
{path: '/teacher',...children: [...{path: 'edit/:id',name: '修改讲师',component: () => import('@/views/edu/teacher/save.vue'),meta: { title: '修改讲师', noCache: true },hidden: true}]
},
2、list.vue - 通过路由携带id进行修改
3、定义API 根据id查询信息
//根据id查询讲师
updateById(id) {return request({url: `/eduservice/teacher/getById/${id}`,method: `get`,})
}
4、根据id回显信息 - save.vue
// 修改请求--根据id回显信息
getInfoById(id) {teacherApi.updateById(id).then(resp => {this.teacher = resp.data.data})
}
5、钩子函数添加判断
created() {// 判断路由跳转时是否携带参数if (this.$route.params && this.$route.params.id) {this.getInfoById(this.$route.params.id)}
}
6、展示 - 点击修改后数据回显
3.8、讲师修改
1、定义API
// 修改讲师信息
updateTeacherInfo(teacher) {return request({url: `/eduservice/teacher/updateById`,method: `post`,data: teacher})
}
2、修改方法 - save.vue
// 修改请求--修改讲师信息
updateTeacher() {teacherApi.updateTeacherInfo(this.teacher).then((resp) => {this.$message({message: "修改讲师记录成功",type: "success",});this.$router.push({ path: "/teacher/table" });});
}
3、区分新增或修改请求(通过路由跳转是否携带id进行判断)
saveOrUpdate() {if (!this.teacher.id) {//没有id值,做【新增操作】this.saveBtnDisabled = true; // 只能点击一次保存操作,防止表单多次保存this.saveData();} else {//有id值,做【修改操作】this.updateTeacher()}
},
3.9、bug解决
场景
- 用户点击修改按钮后不想修改了反而想添加讲师
- 点击添加讲师按钮,此时表单数据未清空
- 将 回显数据流程 封装为
init()
方法(当路由中有id时回显数据,没有就清空表单) - 通过 watch属性 观察路由是否发生变化,变化那就重新执行
init()
进行页面加载
旧代码
created() {// 判断路由跳转时是否携带参数if (this.$route.params && this.$route.params.id) {this.getInfoById(this.$route.params.id)}
}
优化后
methods: {...// 初始化页面init() {if (this.$route.params && this.$route.params.id) {this.getInfoById(this.$route.params.id)} else {this.teacher = {};}},
},
created() {this.init();
},
watch: {// 当路由发生变化时初始化页面$route(to, from) {this.init();}
}
2022年最新《谷粒学院开发教程》:2 - 前后端交互篇相关推荐
- 2022年最新《谷粒学院开发教程》:9 - 前台课程模块
资料 资料地址 后台管理系统目录 前台展示系统目录 1 - 构建工程篇 7 - 渲染前台篇 2 - 前后交互篇 8 - 前台登录篇 3 - 文件上传篇 9 - 前台课程篇 4 - 课程管理篇 10 - ...
- 2022年最新《谷粒学院开发教程》:5 - 章节管理
资料 资料地址 后台管理系统目录 前台展示系统目录 1 - 构建工程篇 7 - 渲染前台篇 2 - 前后交互篇 8 - 前台登录篇 3 - 文件上传篇 9 - 前台课程篇 4 - 课程管理篇 10 - ...
- 2022年最新《谷粒学院开发教程》:4 - 课程管理
资料 资料地址 后台管理系统目录 前台展示系统目录 1 - 构建工程篇 7 - 渲染前台篇 2 - 前后交互篇 8 - 前台登录篇 3 - 文件上传篇 9 - 前台课程篇 4 - 课程管理篇 10 - ...
- 三维电子沙盘 三维数字虚拟沙盘 开发教程第39课 交互触摸查询面板的调用
三维电子沙盘 三维数字虚拟沙盘 开发教程第39课 交互触摸查询面板的调用 查询面板调用: private void Button_Click_11(object sender, RoutedEvent ...
- 前后端解析_好程序员Web前端教程分享前后端分离接口
随着互联网的高速发展以及IT开发技术的升级,前后端分离已成为互联网项目开发的业界标准使用方式.在实际工作中,前后端的接口联调对接工作量占Web前端人员日常工作的30%-50%,甚至会更高.接下来的好程 ...
- 运维开发笔记整理-前后端分离
运维开发笔记整理-前后端分离 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.为什么要进行前后端分离 1>.pc, app, pad多端适应 2>.SPA开发式的流 ...
- 前后端混合开发模式和前后端分离开发模式
前后端混合开发模式和前后端分离开发模式 一.前后端混合开发模式 二.前后端分离开发模式
- uniapp简单搞定支付传统的开发支付需要前后端做很多工作,各种参数的处理,签名,秘钥的验证校验等,尤其是涉及到多种不同的平台支付,更是繁琐;而且以往的支付是由后端主导的,如果后端是个菜鸡,那么做这
uniapp简单搞定支付 传统的开发支付需要前后端做很多工作,各种参数的处理,签名,秘钥的验证校验等,尤其是涉及到多种不同的平台支付,更是繁琐:而且以往的支付是由后端主导的,如果后端是个菜鸡,那么做这 ...
- cbnertvirtual内部框架下载_快速开发,支持前后端分离,微服务框架
JeecgBoot JeecgBoot是一款基于BPM的低代码平台,零代码开发!采用前后端分离架构,支持微服务: SpringBoot 2.x,Ant Design&Vue,Mybatis-p ...
- 【系】微信小程序云开发实战坚果商城-前后端交互之订单实现
第 4-7 课:前后端交互之订单实现 目录 开篇 [系]微信小程序云开发实战坚果商城-开篇 基础篇 [系]微信小程序云开发实战坚果商城-弹性盒子 [系]微信小程序云开发实战坚果商城-ES6 简单入门 ...
最新文章
- jQuery框架学习第二天:jQuery中万能的选择器
- 问题解决:Apache: You don't have permission to access / on this server
- html层次选择器例题,JQuery 层次选择器的例子
- CodeForces - 850C Arpa and a game with Mojtaba(博弈+sg函数)
- php上传图片文件常用的几个方法
- LINUX下载编译ncurses
- python调用matlab
- Java实现两个文件夹之间的同步(改进版)
- 基于R语言的贝叶斯网络模型、现代贝叶斯统计学方法
- 【OS学习笔记】二 汇编语言和汇编软件
- Python 自动获取 Bing 壁纸
- Unity 游戏入门 九、 精灵动画 Sprite Animation
- 在顺丰的历史上,扩大规模的资金来源
- 局域网不能访问的问题
- Python数据分析练习:北京、广州PM2.5空气质量分析(2)
- 2015php网址导航源码,114啦网址导航源码评测 114啦网址导航下载
- Golang优秀开源项目汇总(持续更新。。。)
- python剪切文件
- Java+SSH人力资源管理系统(含源码+论文+答辩PPT等)
- WordPress自定义简码制作写法