• 谷粒学院16万字笔记+1600张配图(五)——讲师管理前端


    项目源码与所需资料
    链接:https://pan.baidu.com/s/1azwRyyFwXz5elhQL0BhkCA?pwd=8z59
    提取码:8z59

    文章目录

    demo05-讲师管理前端

    1.搭建项目前端页面环境

    我们这里用vue-admin-template框架来进行环境搭建

    1.去资料中找到模板压缩文件,有两个,我们使用171KB的那个模板压缩文件

    vue-admin-template和vue-element-admin的区别:前者是精简版,只有最基础的功能,后者功能更多。我们在前者的基础上进行二次开发,把后者当做工具箱,想要什么功能或者组件就去后者那里复制过来

    在这里插入图片描述

    2.解压这个171KB的压缩文件到工作区里面(我的工作区是vs1010)

    在这里插入图片描述

    3.在vscode中以终端方式打开上一步解压得到的文件夹,使用命令npm install进行依赖安装,安装完毕后会自动生成node_modules文件夹,这个文件夹存放的就是安装好的依赖

    在这里插入图片描述

    在这里插入图片描述

    如果下载时爆红,那么此时自动生成的node_modules文件夹里面只会安装部分依赖,并没有将package.json中记录的依赖全都按装,所以我们要删掉这个自动生成的node_modules文件夹,重新执行npm install命令安装依赖,通常多试几次就能下载成功了

    4.上面只是为了让我们熟悉一下流程,其实老师给的有已下载好依赖的后台系统页面,我放在了资料中(苹果电脑不用看4、5步了,因为苹果电脑只能使用npm install命令自己下载依赖,没办法使用已经下载好的依赖)

    在这里插入图片描述

    5.将这个压缩文件解压到工作区中(我的工作区是vs1010)

    在这里插入图片描述

    6.在终端中使用如下命令启动项目,启动后的项目的默认端口号是9528

    npm run dev
    

    在这里插入图片描述

    7.在地址栏输入http://localhost:9528就可以访问了

    在这里插入图片描述

    2.项目前端页面框架介绍

    2.1项目入口

    我们编写的后端程序的入口是main方法,同样的这个前端框架也有入口(有两个入口)

    入口一:vue-admin-1010–>index.html

    不过这个页面只做了一件事:写一个div标签,并给该div标签添加一个id属性。做这件事的意义在讲解入口二时会说到

    在这里插入图片描述

    入口二:vue-admin-1010–>src–>main.js

    该js中先是用import...from...引入了其它组件或者文件,最后new Vue({el: 'app',...}),其中app就是入口一的index.html中div标签的id=“app”

    所以呢,入口一(index.html)写一个div标签用于显示,入口二(main.js)引入了其它组件然后创建vue对象进行操作

    在这里插入图片描述

    2.2框架使用的技术

    我们前端页面环境使用的vue-admin-template框架(模板)主要基于两种技术实现出来。

    vue-admin-template模板 = vue + element-ui

    2.3 项目的目录结构

    1.build目录:放项目构建的脚本文件(一般不用管这个目录)

    2.config目录:基本配置信息

    我们可以在index.js中修改ip、端口号(可以修改但没必要修改),但注意一定要把index.js中useEslint: true改为useEslint: false(这是ESLint插件,这个插件用来检查代码,但是它的检查太严格了,我多敲几个空格多敲几个换行就会被视为错误代码,所以我们改为false,不使用这个插件)

    在这里插入图片描述

    我们在"1.搭建项目前端页面环境"的第6步使用命令npm run dev启动项目时会执行文件dev.env.js(同理如果使用命令npm run prod启动项目时会执行文件prod.env.js)

    dev.env.js和prod.env.js都有BASE_API: '"https://easy-mock.com/mock/5950a2419adc231f356a6636/vue-admin"',这表示要访问的后端接口的地址,这里是默认地址,我们日后(3.1修改前端项目访问路径的第4步)要改成我们本地的后端接口地址localhost:8001

    在这里插入图片描述

    3.node_modules目录:存放下载的依赖

    4.static目录:存放静态资源(一般不用管这个目录)

    5.src目录:

    ①api目录:定义方法

    ②assets目录:存放静态资源(如:css文件、js文件、项目的相关图片…)

    ③components目录:存放一些组件/插件。比如说,我觉得当前这个框架缺少某个功能,那么我就可以引入额外的框架,引入的框架就放到这个目录(components)

    ④icons目录:存放项目用到的图标

    ⑤router目录:路由,就是我们说的菜单

    ⑥store目录:存放脚本文件(一般不用管这个目录)

    ⑦styles目录:存放样式文件(一般不用管这个目录)

    ⑧utils目录:存放框架中用到的工具类(一般不用管这个目录)

    ⑨views目录:存放项目具体的页面

    2.4如何使用框架

    我们用框架的目的是少写代码,更快的完成功能开发,那么理所当然的我们使用的这个前端页面框架也给我们封装了很多功能以便让我们减少代码编写(比如①封装了ajax请求、②以前必须使用babel将es6模块化转为es5模块化才可以在node中执行,现在框架会替我们完成es6转为es5)

    那么我们开发功能时就需要做什么,具体流程是什么呢(这里先混眼熟就行,在后面的"4.4总结"中会细说)

    • 在src目录的api目录下定义方法
    • 在router目录的index.js文件中写路由
    • 在views目录的页面中调用方法,在页面中使用element-ui做显示

    3.后台系统登录功能改造

    3.1修改前端项目访问路径

    1.在终端执行npm run dev命令来启动前端项目,启动成功后在地址栏输入http://localhost:9528进行访问

    在这里插入图片描述

    在这里插入图片描述

    2.在打开的页面按F12打开开发者工具,在开发者工具中点击"Network"菜单,然后点击页面的"Sign in"按钮(点击按钮可能登录不进去,这是因为要访问的这个网站经常崩掉,不用管,第4步我们会把访问路径改为我们自己开发的后端接口的路径localhost:8001)

    在这里插入图片描述

    3.我们点击发送的第一个请求,可以看到请求路径是:

    https://easy-mock.com/mock/5950a2419adc231f356a6636/vue-admin/user/login

    这时我们回过头看"2.3 项目的目录结构"的第2条说的config目录下的dev.env.js和prod.env.js页面共有的BASE_API:

    https://easy-mock.com/mock/5950a2419adc231f356a6636/vue-admin

    发现第一个路径前半部分和第二个路径一样,后半部分多了个"/user/login",此时我们也就明白了:原来前端项目要访问的后端接口的地址就是在config目录下的dev.env.js和prod.env.js页面中的BASE_API设置的呀

    在这里插入图片描述

    4.分析完了现在开始修改后台访问路径:

    将config目录下的dev.env.js中的BASE_API: '"https://easy-mock.com/mock/5950a2419adc231f356a6636/vue-admin"',注释掉,并添加如下这行代码

    BASE_API: '"http://localhost:8001"',
    

    在这里插入图片描述

    3.2稍微看一点点底层

    1.看src–>utils–>request.js:

    在这里插入图片描述

    因为人家框架定义了非20000的状态码都是抛错,所以我们在"demo03-后台讲师管理模块"的"5.1统一返回数据格式"的第2步定义成功的状态码是20000

    2.看src–>api–>login.js:

    在这里插入图片描述

    我们看login.js定义的方法中的这两个:login方法和getInfo方法:

    • 这两个方法的返回值都是request(…)方法,包括以后在api目录下定义的所有方法我猜测返回值都是request(…)方法,因为在request(…)方法中框架给我们封装了axios异步请求(这里不细说了)
    • url: '/user/login'url: '/user/info'就是axios要访问的路径,所以我们等下需要在后端的控制层中编写两个方法,使访问/user/login/user/info时可以执行对应的方法

    3.看src–>store–>modules–>user.js:

    在这里插入图片描述

    登录账号时底层会做两件事:登录&获取用户信息。

    看"登录"方法中,成功调用login方法(在刚刚的第2条说过这个方法,这是在api目录下定义的方法)后要做的事在then(response => {…})里面编写了,省略号中有部分代码是:const data = response.datacommit('SET_TOKEN', data.token),从这里我们可以看出来后端对应方法返回的数据中一定要有token。同理,看"获取用户信息"方法,我们也知道了后端对应方法返回的数据中一定要有roles、name、avatar

    3.3在后端开发接口

    在service_edu模块的控制层创建一个EduLoginController类,并在类中编写代码

    @RestController
    @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", "admin")
                    .data("avatar", "https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif");
        }
    }
    

    在这里插入图片描述

    • login方法中的return R.ok().data("token", "admin");:我们在"3.2稍微看一点点底层"的第3条已经详细解释过了为什么返回的数据需要有token。info方法中的 return R.ok().data("roles", "[admin]").da......也是同理
    • 我们现在先来模拟登录,也就是不和数据库挂钩,所以:①数据啥的都是我们自己捏造的②实际开发中这两个方法肯定都会有参数,但我们现在只是模拟,先不写参数

    3.4检查login.js有哪里需要修改

    1.因为我们在"3.3在后端开发接口"编写代码时设置路径是/eduservice/user/login/eduservice/userinfo,所以我们要去src–>api–>login.js中将login方法中的url: '/user/login'改为url: '/eduservice/user/login';将getInfo方法中的url: '/user/info'改为url: '/eduservice/user/info'

    2.我们在"3.3在后端开发接口"编写的login方法上有一个注解是@PostMapping; info方法上有一个注解是@GetMapping,那么就需要让login.js页面的login方法中的method是post;让getInfo方法中的method是get。恰好这两个方法的method本来就是这样的,所以不需要修改

    3.我们在"3.3在后端开发接口"编写的login方法和info方法都没有参数,所以login.js页面的login方法中的data: {...}和getInfo方法中的params: {...}暂时都无实际意义,暂时用不上,但也不用管它们,就在这儿放着就可以了

    所以说呢,login.js页面中只需要修改login和getInfo方法的url,别的地方不需要修改。修改后的login.js如下:

    在这里插入图片描述

    3.5测试&跨域问题

    1.启动后端项目

    在这里插入图片描述

    2.在终端使用命令npm run dev启动前端项目

    在这里插入图片描述

    3.在地址栏输入http://localhost:9528进入登录页面,然后按F12打开开发者工具,接着点击"Sign in"按钮发现还是不能登录,我们点击"Console"菜单去控制台看一下输出了什么错误信息

    在这里插入图片描述

    No 'Access-Control-Allow-Origin’这在术语上是叫跨域问题

    什么叫跨域:通过一个地址去访问另外一个地址,这个过程中如果①访问协议(http、https)、②ip地址、③端口号这三处只要有任何一处不一样,就叫做跨域

    我们现在是通过http://localhost:9528去访问http://localhost:8001,这两个地址的端口号不一样,所以会出现跨域问题

    4.跨域问题的解决方式有很多种,简单列举两种:

    • 在后端接口controller上添加注解@CrossOrigin(常用)
    • 使用网关解决(后面会讲到)

    我这里就是使用添加注解来解决跨域问题的:

    在这里插入图片描述

    在这里插入图片描述

    5.重启后端项目,在地址栏输入http://localhost:9528进入登录页面,然后按F12打开开发者工具,接着点击"Sign in"按钮,此时就可以正常登录进去了。

    并且注意看,它既向.../user/login发送了请求,又向.../user/info发送了请求,这就证实了我们在"3.2稍微看一点点底层"中第3点说的话:登录账号时底层会做两件事:登录&获取用户信息。

    在这里插入图片描述

    在这里插入图片描述

    可能有朋友会有疑问:为啥每个请求都是请求了两次呢?

    这是浏览器的机制,就拿第一个请求login举例:

    该路径的第一次请求的请求方式是options;第二次请求的请求方式是post。

    第一次的请求可以理解为是一个预请求,只是为了测是否能和后台服务器接口连通,如果能连通才会进行第二次的真正请求,不过第一次请求不会返回任何数据。

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    4.前端框架开发过程介绍

    4.1在src–>router–>index.js中添加路由

    在这里插入图片描述

    怎么编写添加路由的代码呢?我们可以看一下Example菜单的示例代码,以后路由就根据这个示例代码修改就可以了

    在这里插入图片描述

    在这里插入图片描述

    component: () => import(...) 就是路由对应的页面,这样的话,点击某个路由,就可以显示路由对应的页面内容

    4.2在src–>views中创建vue页面

    既然点击路由可以显示路由对应的页面内容,那么相应的我们就需要创建页面

    1在哪创建vue页面:

    看上面那张图中的component: () => import('@/views/table/index'),我们根据路径可以找到view–>table–>index

    在这里插入图片描述

    所以我们就知道了,我们创建的页面是在views目录下(准确来说,是views目录的子目录下)

    我们上面说的页面存放位置是框架默认的,当然了,你说我不想按照框架默认的存放位置(先在views目录下创建子目录,然后在子目录下创建页面),我想在views目录下创建一个子目录,然后在子目录下再创建一个子目录,最后才在最里层的目录中创建vue页面,这当然是可以的,但是别忘了需要配套地填写router–>index.js页面的component: () => import(...)中的路径。反正页面创建在哪都可以(大前提是在src目录下),只要配套填写路径就可以了

    2.为什么创建的是vue页面而不是html页面或其他页面?

    看上面那张图,人家创建的就是vue页面

    4.3在vue页面中编写功能

    老规矩,先看人家怎么在页面中编写代码的:

    1.看src–>views–>table–>index.vue页面中的import { getList } from '@/api/table',这我们在"demo04-前端技术"的"9.3.1第一种写法"说过,是引入js文件中定义的方法

    在这里插入图片描述

    2.我们根据import { getList } from '@/api/table'可以去api目录下找到table.js文件,发现这个js文件是用来定义方法的。这样我们也就清楚了下一步应该干嘛:在api目录下创建js文件,定义方法

    在这里插入图片描述

    3.回到最初的问题:我们需要在vue页面中编写什么代码?

    先再看一下vue页面:

    在这里插入图片描述

    现在我们知道vue页面就需要编写什么代码了吧:先使用import...from...引入方法,然后编写data():{...},created(){...},methods:{...},最后用element-ui显示数据内容(就在该页面的1-43行,太多了,所以我就没有放到截图里面)

    4.4总结

    • 在src–>router–>index.js中添加路由
    • 在src–>views中创建vue页面
    • 在src–>在api目录下创建js文件,定义方法
    • 在创建的vue页面中编写代码
      • 引入api目录下定义的方法
      • 编写data():{...},created(){...},methods:{...}
      • 用element-ui显示数据内容

    5.讲师列表

    5.1在src–>router–>index.js中添加路由

    1.随便找一段例子的代码,将代码复制粘贴

    在这里插入图片描述

    下面是复制粘贴好的indes.js页面:

    在这里插入图片描述

    2.将我们刚刚复制粘贴过来的代码根据需要进行修改,修改后务必保存修改

    在这里插入图片描述

    3.如果后端、前端项目都已启动,那么在地址栏输入http://localhost:9528进行访问,在登录页面点击"Sign in"登录进去后效果如下:

    在这里插入图片描述

    5.2创建路由对应的页面

    我们在"4.2在src–>views中创建vue页面"中说过,我们可以在任何地方(大前提是在src目录下)创建vue页面,只要配套的修改router–>index.js页面的component: () => import(...)中的路径即可

    1.那么我们就可以在src–>views目录下创建一个目录edu,在edu下再创建一个目录teacher,最后在teacher目录下创建页面list.vue和save.vue

    在这里插入图片描述

    2.配套的修改index.js中component: () => import(...)的路径,修改后记得保存修改

    在这里插入图片描述

    3.在list.vue中编写代码

    
    

    在这里插入图片描述

    在我们以后创建的所有vue页面中都是必不可少的,这是人家封装的,省略号的内容我们根据具体需求写

    4.在save.vue中编写代码

    
    

    在这里插入图片描述

    5.3在api目录下创建js文件,定义方法

    1.在api目录下创建teacher文件夹,然后在该文件夹下创建teacher.js文件

    在这里插入图片描述

    2.老办法,参考框架怎么定义方法的:将api–>tables.js中的代码复制粘贴到teacher.js中

    在这里插入图片描述

    有人可能要问:return request({...})中的request方法是干嘛用的?

    这是框架给我们做的封装,只要我们调用了getList方法,就会使用axios发送ajax请求

    3.es6模块化操作有两种写法,框架给的是第一种写法,我们开发中用第二种写法("demo04-前端技术"的9.3.2第二种写法)比较多,所以我们对teacher.js的代码进行修改

    import request from '@/utils/request'
    
    export default {
        getList(params) {
            return request({
              url: '/table/list',
              method: 'get',
              params
            })
          }
    }
    

    在这里插入图片描述

    4.好,我们现在根据需要来修改定义方法

    先看我们后端控制层的EduTeacherController类和类中的方法:条件查询讲师带分页(pageTeacherCondition)

    在这里插入图片描述

    在这里插入图片描述

    我们需要知道这几个东西:

    • EduTeacherController类的路径是/eduservice/edu-teacher
    • pageTeacherCondition方法的路径是pageTeacherCondition/{current}/{limit}
    • pageTeacherCondition方法的参数是current, limit, teacherQuery。分别表示当前页、每页记录数、条件对象
    • pageTeacherCondition方法的请求方式是post
    • pageTeacherCondition方法的第三个参数用@RequestBody注解修饰,所以前端传过来的第三个参数需要是json数据(忘了这个注解的可以去"demo03-后台讲师管理模块"的"7.5改进"回顾一下)

    知道了上面这些,我们就可以修改teacher.js中定义的方法了:

    • url的参数需要修改,有两种方式(建议用第一种)

      • url: ‘/eduservice/edu-teacher/pageTeacherCondition/’ + current + “/” + limit
      • url: `/eduservice/edu-teacher/pageTeacherCondition/${current}/${limit}`
        • 注意,这不是单引号,是飘号(在键盘"Esc"的下面)
    • 方法参数改为current, limit, teacherQuery。分别表示当前页、每页记录数、条件对象

    • 请求方式改为post

    • 删去"params",添加一行代码data:teacherQuery,这表示把teacherQuery对象转换为json数据传递到接口中

    • 方法名改为getTeacherListPage

    5.修改后的teacher.js完整代码如下:

    import request from '@/utils/request'
    
    export default {
      //1.讲师列表(条件查询带分页)
      //current:当前页  limit:每页记录数  teacherQuery:条件对象
      getTeacherListPage(current, limit, teacherQuery) {
        return request({
          url: `/eduservice/edu-teacher/pageTeacherCondition/${current}/${limit}`,
          method: 'post',
          //data: teacherQuery表示把teacherQuery对象转换为json数据传递到接口中
          data: teacherQuery
        })
      }
    }
    

    在这里插入图片描述

    5.4在list.vue页面调用5.3中定义的方法

    1.既然用人家的框架,就要用人家规定的格式编写代码,参考人家给的src–>views–>dashboard–>index.vue页面我们可以知道,需要先写一个,然后才能在省略号的位置编写我们的核心代码

    在这里插入图片描述

    2.在src–>views–>edu–>teacher–>list.vue页面先敲一个人家就会给提示

    在这里插入图片描述

    在这里插入图片描述

    3.将src–>api下的teacher文件夹改名为edu(没有任何逻辑,只是因为老师这里想改名,那我也跟着改)

    在这里插入图片描述

    4.需要先在页面中引入teacher.js文件

    import teacher from '@/api/edu/teacher'
    

    在这里插入图片描述

    5.核心代码是有固定结构的,我们在"demo04-前端技术"的"4.axios"的第5步说过固定结构,只是框架给我们进行了封装,不再需要我们自己创建vue对象,下面我们写出核心代码的固定结构

    //编写核心代码
    // data: {
    
    // },
    data() { //定义变量和初始值
      return {
    
      }
    },
    created() { //页面渲染之前执行,一般用来调用methods中定义的方法
    
    },
    methods: { //创建具体的方法,调用teacher.js中定义的方法
    
    }
    

    在这里插入图片描述

    其中data: {...}这种写法没问题,不过我们习惯用第二种写法:data() {return {...}}解释一下这种写法:data是一个方法,我们在方法中加一个return,在return中写内容。

    emmmm,离谱的是,弹幕有朋友说第一种写法是错误的,只能用第二种,我这里不深究了,反正我用的就是第二种

    6.完整的teacher.vue代码如下:

    
    
    
    

    在这里插入图片描述

    有人可能要问了,使用axios发送ajax请求不应该是getList() {axios.post("...").then(...).catch(...)}吗,为什么这里是teacher.getTeacherListPage(this.page, this.limit, this.teacherQuery).then(...).catch(...)

    这是因为人家框架给我们做了封装,我们执行teacher.js中定义的getTeacherListPage方法的过程实际上就是使用axios发送ajax请求的过程(我们在"5.3在api目录下创建js文件,定义方法"的第2步就已经说过了)

    5.5显示讲师列表

    1.启动后端项目和前端项目,访问http://localhost:9528,在首页打开开发者工具,点击"讲师列表",查看控制台输出

    在这里插入图片描述

    2.上图中使用大方框圈起来的就是请求成功之后返回的信息,所以我们想要获取讲师列表就需要用这个代码:response.data.rows,知道了这些,那么list.vue中的console.log(response)就没什么用了,我们把它注释掉就可以了,然后我们给list.vue页面中添加如下代码:

    this.list = response.data.rows
    this.total = response.data.total
    console.log(this.list)
    console.log(this.total)
    

    在这里插入图片描述

    3.刷新页面,看控制台的输出:

    在这里插入图片描述

    4.现在我们已经可以拿到数据,接下来我们在list.vue页面的template标签的div标签下编写代码使数据以列表的形式在页面显示,这里我们使用element-ui组件实现

    ①进入element-ui的官网https://element.eleme.cn/#/zh-CN,点击组件的"查看详情"

    在这里插入图片描述

    ②点击"Table 表格"就会有很多示例供我们选择,我们这里就使用第一个吧。点击"显示代码"

    在这里插入图片描述

    ③为了便于观看,我们将示例的代码复制到文件中

    在这里插入图片描述

    • :data="tableData"v-bing:data="tableData"的简写形式(忘了的可以去回顾"demo04-前端技术"的"3.3基本数据渲染和指令"),用来和tableData单向绑定以获取数据
    • element-ui给我们封装过了,底层会自动遍历数组,不再需要我们使用v-for来遍历数组
    • 标签的属性prop="date"和tableData中的date对应
    • 标签的属性label="..."就是表头

    ④老师给的有代码,我们直接复制粘贴到list.vue页面的template标签的div标签下

    
    
    
      
        
      
    
      
      
      
        
      
    
      
    
      
    
      
    
      
        
      
    
    

    在这里插入图片描述

    • 我们在"5.5显示讲师列表"的第2步使用代码this.list = response.data.rows将讲师数据存放到了list变量中,所以截图的第6行是:data="list",以获取讲师数据
    • 截图第7行的element-loading-text="数据加载中" 作用是:点击前端页面的"讲师列表"后,如果网速比较慢,还没有获取到数据并展现,此时就会显示"数据加载中"。可有可无,如果不需要这个功能,就把截图中第5行的v-loading="listLoading"和第7行的element-loading-text="数据加载中"删掉,听弹幕说如果使用这个功能日后可能会报错,吓得我赶紧把这两行代码删了
    • 截图第17行的{{ (page - 1) * limit + scope.$index + 1 }}是显示序号,不用太深究,固定用就可以了
    • 截图第24行的