el-admin实战解析


与你相识


博主介绍:

– 本人是普通大学生一枚,每天钻研计算机技能,CSDN主要分享一些技术内容,因我常常去寻找资料,不经常能找到合适的,精品的,全面的内容,导致我花费了大量的时间,所以会将摸索的内容全面细致记录下来。另外,我更多关于管理,生活的思考会在简书中发布,如果你想了解我对生活有哪些反思,探索,以及对管理或为人处世经验的总结,我也欢迎你来找我。

– 目前的学习专注于Go语言,辅学算法,前端领域。也会分享一些校内课程的学习,例如数据结构,计算机组成原理等等,如果你喜欢我的风格,请关注我,我们一起成长。


Introduction

因为自己在校做一个项目的时候用的是团队自己搭建的项目,基于el-admin,不过后端不是spring boot,而是gin框架(Go语言),虽然后端框架不同,不过思想也大差不差,记得刚接触这个框架的时候,官方有一些使用手册,但是不够详尽,然后去网上找了一圈也没什么教程,这让我很苦恼,经过了一个月左右时间的磨练,也有了自己的一些理解,希望能整理出来,抛砖引玉。

也许不能把el-admin的整个脉络清晰的叙述出来,但是做到能够基本的使用,入门,应该还是可以的,有问题的话可以评论,我们一起讨论。

eladmin 官方快速上手地址 :
https://el-admin.vip/guide/#%E5%9C%A8%E7%BA%BF%E4%BD%93%E9%AA%8C
预览地址 :https://el-admin.xin/system/timing
账号:admin 密码:123456


我们团队基于el-admin开发的go-sword-admin开源地址(github):
前端:
https://github.com/sanyueruanjian/go-sword-admin-web
后端:
https://github.com/sanyueruanjian/go-sword-admin

下面是el-admin的预览画面,它迭代到如今,已经有了几万行代码,整个体系已经比较的庞大了。

不过因为能力的原因,我可能无法把el-admin里的内容都覆盖到

我们这次做的项目大概是这个样子,接下来我的讲述将基于下面这个项目——面向实战学习。


项目框架

第一步需要先看一下项目的文件架构,让自己面对一个全新的架构不至于那么慌乱。

前端

  • 【public】:里面存的是el-admin的图片和默认主页,对我们做项目没什么价值。
  • 【src】:里面存储了项目源码
  • 【api】:存储各个模块的api函数,el-admin使用RESTful风格来管理接口,接口就是前端通过给后端发送请求,后端接收到请求之后,进行自己的逻辑处理,最终把数据可以返回给前端,这样前端就收到了数据。
  • 【assets】:原el-admin的静态资源文件夹,存放了一些图片和图标,不过我们的项目并没有用到。
  • 【components】:一些公共组件,比如搜索框,增删改按钮等
  • 【layout】:这个文件里存储了el-admin的侧边栏和主体框架的布局,一般不对这里进行更改。
  • 【mixins】:mixins 混入,这里要先提及一下Vue中的mixin(混入),简单介绍来说,相当于Java中的extends ,继承。

简单的小例子:
一个Vue组件(组件1)去混入另外一个Vue组件(组件2),相当于这个组件(组件1)继承了被混入组件(组件2)的属性。其中的data域中的不同名属性直接都保留,同名属性取这个组件(组件1)的值,methods域规则同data域,钩子函数则二者的都会被执行,但被混入组件(组件2)的钩子函数会先执行,具体的可以查看Vue.js中mixin的官方介绍.

  • 【router】:存放了路由相关的信息,一般也不怎么修改,包括动态路由,静态路由的信息。
  • 【store】:存放了框架中的一些状态信息,算是框架的一些配置信息,比如token的获取,token的过期时间,是否显示某些东西,我们这次做项目没有用到里面的内容,关于权限和token这一块都已经封装好了,我也就没看里面的源码。
  • 【utils】:工具包,里面存放了一些框架的工具方法,比如获取token,设置token,标题,请求,验证等。

我找到了另一篇博客介绍了一些这里常用的工具方法(博客地址在最下面):

getToken():获取token
setToken(token, rememberMe):设置token信息
parseTime(time, cFormat):将时间解析为字符串,传闯入data和格式,返回相应格式的数据
formatTime(time, option) :格式化时间,和parseTime是不同的,这个方法可以将时间具体格式成 ‘刚刚’、‘一天前’、‘一小时前’…等等等
getQueryObject(url):可以获取url路径上的参数列表,封装成一个JS对象返回给你。例如https://mp.csdn.net/console/article?spm=111&id=222 ,返回的object{spm:111 ,id:222}
byteLength(str):返回字符串的字节长度
cleanArray(actual):这个还是比较常用的,可以帮助我们将数值中的空值给清除掉
param(json):这个就更常用了显现是调用了上边的cleanArray,清除jason中的空值,
param2Obj(url):与getQueryObject的区别在于,这个是返回的一个字符串对象(JSON对象)
html2Text(val):就像函数名所写的那样,将一个节点转化为 html代码。
objectMerge(target, source):合并两个对象,相同字段保留source中的值。
toggleClass(element, className):切换一个类名,类存在则删去,不存在则添上。
debounce(func, wait, immediate):防抖函数,防抖:触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间。
deepClone(source):deep深度拷贝,这只是deep copy的一个简单版本,有很多边盒缺陷如果你想使用一个完美的深拷贝,可以使用lodash的.cloneDeep
uniqueArr:根据传入的数组,生成一个无重复值的数组(内部通过Set集合实现)
createUniqueString():生成一个唯一码,类似uuid
hasClass(ele, cls):检查节点是否具有该类。
addClass(ele, cls):给节点添加该类
removeClass(ele, cls):删除该类
regEmail(email):对邮箱进行加密,例:123456789@163.com =>123****@qq.com
regMobile(mobile):对手机号进行加密,例:15500001234 => 155****1234
downloadFile(obj, name, suffix):下载文件,原理帮助我们生成一个不显示的a连接,然后触发点击事件,然后删除a连接。

  • 【view】:里面做我们的页面渲染

整个前端内容很多,但是如果想在el-admin基础上进行开发的话,其实只需要重点关注apicomponentsutilsviews这几个就可以了。

后端 (Gin框架)

  • 【app】:下面存着我们的后端项目文件
  • 【admin或smartcampus】:这两个都是我们项目的文件,下面往往都会有四个文件夹,apis,ctrl层,用来接收请求,接收前端传来的数据。 models,Dao层,用来操作数据库。 router,存放本模块各种路由信息。 service,service层,用来做一个承上启下的过程,apis获取前端传来的参数之后,自己会进行校验,然后调用service层的函数,把接收的参数当做参数传递,此时service层的文件就可以根据自己的逻辑对这些传来的数据进行处理,如果有需要调用数据库的事情,比如增删查改操作,就在service层调用models的函数来获取数据。
  • 【common】:里面写了各个模块的一些公共的方法,比如获取用户的上下文,错误处理,数据库迁移的设置,服务启动,路由设置等,基本上还是原框架所用到的一些方法,内容也不多。
  • 【logs】:存放了各个层级的error
  • 【pkg】:里面存的是第三方库的引用,比如casbinjwtfile的封装方法。
  • 【settings】:这个里面保存了settings.dev.ymlsettings.prod.yml文件,也就是程序各种各样的配置,比如端口,ip,一些全局的配置等。
  • 【utils】:写了各个模块的工具方法,不过我们的项目也用的不多。
  • 剩下的都是git,或者go的包管理,主程序文件了。

源码分析

我感觉el-admin最难以理解的,还是前端,所以笔墨可能会偏前端一些。 我想把我关于这块的知识阐述出来,但是我一直没找到一个比较好的方式,所以就常规性的,第一模块是文件架构,第二模块源码分析。

但是怎么分析才能让大家有所获益呢?后来我想了想,前端就带大家捋一个页面是如何形成的,然后重点再说说各个我觉得比较重要的内容。

后端就带大家纵览全局,看看整体流程,以及如何写一个接口。

前端

一个页面是如何形成的?

新建文件夹

首先,这个框架一个中规中矩的页面,大概就是这个样子,el-admin是基于element组件的,所以我们在开发el-admin的时候,需要先去了解一下element组件。

需要建立这样一个页面,我们首先需要去【views】中新建一个自己模块的文件夹,假如说就叫model1吧,然后可以在这个文件夹下再新建一个文件夹,比如test1吧,然后可以创建一个index.vue文件。

类似于下面这样,此时我们已经相当于建立了自己的页面文件,但是如何在网页的菜单中点击某个菜单访问index.vue需要我们进行一些设置。

这些名字都无所谓,包括index,都可以改成其它的,只需要配置好就可以了。
在这里插入图片描述

新建菜单

我们需要在页面左侧的菜单栏的最下面,出现一个测试管理的下拉菜单,然后里面有一个测试二级菜单,当点击这个测试菜单,就会跳到我们刚才新建的model1/test1/index.vue页面。

我们进入菜单管理,然后点击新建按钮。

  • 菜单类型:有目录菜单按钮三种类型,所谓的目录,就是左边你所看到的系统管理学生管理类别管理考评管理这些一级标题,这也是我们在写一个新的模块的时候,所最先去做的事情。
  • 菜单图标:作为展示的图标
  • 外联菜单:我们设置非外联菜单就可以了,外联菜单是指你需要跳转到外部的链接,比如说百度,比如说搜狐等,关于这部分的设置,在el-admin的前端手册中有说明,此处不在赘述。
  • 菜单可见:菜单可见是指是否在侧边菜单栏中显示。
  • 菜单排序:后端可以通过这个排序数字来对菜单进行一个排序,在有些时候有用,比如你创建了一个model1model2model3三个模块,你就是想让他们按照某个顺序展示出来,就可以通过这个排序的数字来控制。
  • 路由地址:就是浏览器访问这个菜单的地址,我这里写的是test,那么访问这个顶级类别下的二级类别就应该是http://127.0.0.1:8000/test/xxx

通过下面的方式,我就创建了一个测试管理模块。

可以看到我们已经创建成功了。 此时常理来讲,你在侧边栏是看不到这个菜单的——即使你新建了,不过不要着急,我们还是一股脑的再建一个二级菜单,一块让它显示出来。

我们刚才建立了一个菜单类型为目录的菜单,现在我们要创建一个菜单类型为菜单的菜单,也就是我们的二级标题,顺带插一嘴,按钮类型的作用不在页面显示上,而是为了控制权限,等我到casbin权限那一块再细细讨论。

我就只解释几个字段:

  • 路由地址:就是访问这个菜单的URL地址,我写的是test1,它的上级类目是我们刚刚创建的测试管理,它的路由地址是test,而我们的测试一二级标题的路由地址是test1,那么也就是说访问测试一的url地址应该是http://127.0.0.1:8000/test/test1/xxx
  • 组件路径:是当我们点击测试一这个二级标题,访问http://127.0.0.1:8000/test/test1/的时候,会渲染哪个页面?这个时候就把我们刚才创建的model1/test1/inddex用上了,你可以根据自己的名字来创建。
  • 组件名称和菜单缓存是相互的关系,如果不用菜单缓存,组件名称可以不填,其它的字段,我也不是很清楚了,暂时没用上。


这样就可以看到我们已经创建好了测试一

给角色分配菜单

el-admin的菜单是按照角色来分配的,你可以控制某个角色能看到某些菜单,相应的不让看到某些菜单的话,对应的接口,这个角色也无法访问,这个api的权限控制使用到了casbin,暂且不表。

当我们点击角色管理,因为我登陆的是admin账号,属于超级管理员的角色,所以我就设置超级管理员这个角色的菜单分配了,这个地方有个坑,就是很多人会去点击那个选择框,会发现右边的菜单分配并不会变化,那是因为勾选选择框是代表对这个用户进行操作,并不是菜单分配,只需要点击一下这个用户的空白地方,右边就会显示这个用户的菜单维护情况了,我们看到我们刚才新建的测试管理模块并没有被勾选上。

我们把它勾选上,然后点击保存,保存会等待一下,其实这个时候后台在为这个用户添加该测试模块的一些权限配置。

保存成功之后刷新页面就能看到我们创建的测试管理了。

跳转到开发页面

此时我们点击我们创建的测试一,会发现和我们测试的猜想是一模一样的,我们访问了/test/test1地址,然后访问了我们创建的index.vue文件,这里面是我复制的另一个页面的数据。

如果你要开发一个模块的话,现在就可以点击那个vue文件进行开发了,接下来我会带着你解析一下这个vue文件的构成。

vue文件构成,如何在el-admin前端的基础上写出我们想要的样子?

el-admin的各个页面基本上都是下面的这种结构,大差不差,不过有的时候它可能无法满足我们的要求,我们可能会需要自己去做一些个性化的改善。

刚才我们看到的页面就是下面的代码。

  • 【template】:整个页面的内容写在这个标签下
    • 【app-container】:这个里面包含了所有的主体内容。
    • 【head-container】: 这个div里面建立了input搜索框日期搜索框搜索按钮与重置按钮,以及第二排的新增修改删除导出按钮,和右边的三个按钮。
    • 【el-dialog】:当点击添加编辑按钮的时候会弹出这个对话框,是element的组件。
    • 【el-table】:展示的主题控件,是element的组件
  • 【defaultForm】:里面定义了表单的初始值,以及控件数据源的绑定,也涉及到框架内部对字段的维护,比如点击弹出框的取消按钮,消除所有的内容,就需要把弹出框的变量都写在defaultFrom中。
  • 【export default】:这一块定义了核心的内容
    • 【name】:这个对标的是我们创建菜单的时候,有个组件名称 字段,用于菜单缓存,不过我们也没用到,所以写不写都行。
    • 【components】:这是我们的页面中所用到的组件,我这里引用了六个组件,前五个是比较常用的,udOperation是表格中最右边的编辑删除按钮,DateRangePicker是日期搜索框需要用到的,rrOperation是搜索框右边的搜索重置按钮,pagination是分页组件,crudOperation是搜索框下面的四个按钮,IconSelect是我们需要去选择图标的时候用到的组件。
    • 【cruds】:这个里面定义了一些进入这个页面的时候,对框架进行一些初始化的内容,比如title,中间table所访问的url地址,api的引入地址,或者一些其它的设置等,总之当你进入到这个页面的时候,会有一大堆的东西可以提前设置一下,有些是必须要设置的,有些可以先不设置。 这个crud常常指代的就是el-admin这个框架的运转。
    • 【mixins】:设置混入模式,不过因为我个人对前端并不是很专精,所以这个我不是很清楚,不过我大概知道混入模式的各个模块可以共用属性,至于为什么要用这几个就不太清楚了,参考其它的页面用的是这几个,就照着用了。
    • 【data】:设置一些变量,以及rules验证
    • 【methods】:这个就不多说了,关于本页面的js操作就在这里写了。
template页面渲染
搜索和crud按钮

接下来我们就专门讨论一下页面渲染这一块,看看各个部分是怎么组成出来的,以及,如何写出我们想要的样子。

我们先看下面的蓝色部分,首先第二句有一个v-if来控制这个div的显示与隐藏,可以看得出来是crud的searchToggle属性来控制的,不过我暂时还没有弄明白它具体有什么用,待日后再填吧。

紧接着是一个el-input,这里面的各个属性大家可以自己去查一查,class也是框架自带的,需要重点关注的有三个属性:

  • 【v-model】:你可以写query.xxx的名字,这个地方的作用是当你写的是query.blurry时,当你点击搜索按钮,搜索框的内容发入后端的参数名就是blurry,同样的,当你写query.name的时候,在输入框中输入内容,然后点击搜索,就会发现参数变成了name,至于点击搜索去访问什么url地址,去哪里设置接口的地址,我后面再讲。
  • 【placeholder】:这个就是当控件没有内容的时候的提示,你要根据你的业务进行填写。
  • 【keyup.enter.native】:这个是当你在这个控件输入内容之后,你按了一下enter键,进行的操作。 crud.toQuery就是搜索的方法,也就是当你在搜索框内输入内容,你可以点击搜索按钮来执行搜索,也可以按enter键来执行搜索。

接下来的是【date-range-picker】组件,这个组件就是我们的时间搜索框,它绑定的query.createTime和搜索的有些不同,这个字段相对固定,因为当你点击搜索的时候,会去获取createTime这个字段的值,然后进行一定的处理,再发出去。 这也是为什么当你选择时间再搜索会发现多了两个参数,一个是startTime,一个是endTime,这都是框架里写好的,不过你要是想改,也可以去改,后面介绍到crud.js的时候,我会和你讨论的。

总之它会接收query.createTime这个参数,然后它是一个数组,里面存了开始日期和结束日期,也就是格式为[start,end]这样的格式,crud会对它进行处理,最终再把他们给两个参数传给后端。

在接下来,你会看到<rrOperation /> 这一行信息,如果你追踪到这个组件的话,会发现它就是搜索重置按钮。

紧接着又看到了<crudOperation :permission="permission" />这一行,这是第二排那四个按钮,以及第二排最右边还有三个不显眼的按钮,permission定义了这些按钮的权限,这个等讲到js代码的时候再说。


这样第一部分我们就讲完了。

点击新增和编辑的弹出框

第二部分是下面的代码,它是一个对话框中套了一个表单控件。

首先说说<el-dialog>的属性:

  • 第一行为false是为了控制不能点击对话框外空白的地方关闭对话框。
  • 第二行表示当你点击对话框的右上角叉号的时候,会去调用crud.cancelCU函数,而这个函数会将对话框关掉。
  • 第三行可以看出crud是如何控制对话框的开启和关闭的,是靠crud中status下的cu属性,通过控制它的属性来控制对话框的开启和关闭,至于右边的showInsertDialog属性,那是我自己加的,是我想在crud的基础上,再限制一些条件才能开启。
  • 第四行设置了对话框的标题,它是通过crud.status.title来获取的,而这个属性,在下面script中会有赋值。
  • 剩下的属性自己查吧。

接下来就说说el-form组件

el-formrefmodel属性必须是form(框架内进行维护的就是这个名字,除非你有其它的用处),也就是说只有为form这个名字,它才会被crud检测到,上面那些crud.xxx的属性才能作用到这个对话框上。

接下来的item,你就可以自己去百度查如何写了,或者参考el-admin的其它新增页面,看看是怎么写的,自己做一些修改,这个不是我们的重点,就不赘述了。

唯一一点需要强调的是各个item项下的控件的v-model属性绑定的都是form.xxx,需要写成这样的形式,而item的prop属性一般和xxx相同(参考上图的积分下限即可,prop=lower_limit,v-model=form.lower_limit),然后这些xxx都需要在下面的defaultForm属性中定义下。

当你点击确定,发送表单的时候,prop属性就是你发给后端的参数,比如积分下限,我们输入了-1,点击确定,发送给后端就是lower_limit:-1v-model.number可以控制发送的数值为数字,如果你发送的无法转为数字,vue会发送原本的字符。

主要需要考虑一个这些输入框和crud的协调问题,既然我们需要crud的帮助,就要遵守crud对我们制定的规则。

表格

这常常是我们对这个页面最关心的部分。

接下来我们来看看这段代码

还是先看看属性,有三个关于crud的:

  • 【v-loading】:这个是控制表格加载的,为true就加载,为false就停止加载,crud有一个loading属性来控制,比如添加后要重新加载一下,编辑要重新加载一下等等。
  • 【data】:这个是表格的数据,等于crud.data,而crud.data属性会获取后端传来的数据,这个我们后面再说。
  • 【selection-change】:这个是当你打勾表格的数据的时候,crud会有一个selections属性来存储对应行的数据,是一个列表。

    属性讲完之后,就会表格各个列的名字了,其中会发现有三个地方比较瞩目:
  • 【考评id和积分类别id】:v-if=false就是不显示出来,既然不显示出来,又为什么要在这里呢?是因为在编辑某一条数据的时候,我们往往需要携带这一条数据的id给后端,那么我们就可以通过这个隐藏的列来拿到id。
  • 【创建日期】:这一列我们用parseTime来将后端传过来的时间戳转为日期。
  • 【操作】:也就是最右边的两个按钮,它是调用了<udOperation>组件,这个组件下也有permission,可以控制权限,也就是哪个角色会显示哪个按钮。

另外一个最重要的就是各个列的prop属性不是乱写的,需要根据后端传来的参数来填写,table会自动的填充对应的数据。
比如你想让某一列得到超级管理员这个值,那就把它的prop设置为creator

分页组件

这个用它默认的就可以了,只要数据返回的符合规范,就没有问题。

script
import

第一部分当然是import,这些都是我们要用到的内容,第一行是我们的api的位置。

可以看到我在api文件夹中创建了我们的模块,里面存放了本模块的api

可以让你看看,大概是这个样子,你需要注意这里的add,del,edit三个函数,因为他们的名字不能更改,讲到下面的URL的时候再说这个事情。

defaultForm

这里就把form中的各个参数写下来就可以了,可以给一些默认值,null就代表空。

export

之前讲过的就不讲了,重点讲一下前面的cruds(),这个是crud内部的方法,用来作初始化。

title属性会控制弹出框的标题,如果你写“考评类别”,crud会存title为“考评类别”,当你点击新增按钮的时候,它会在title的前面加上“新增”,所以最终呈现的就是“新增考评类别”,当点击编辑就变成了“编辑考评类别”,但其实新增和编辑都是用的同一个对话框。

url属性非常的重要,这一个地址影响了很多,它就是我们访问的api地址。

当我们刚进入到这个页面的时候,它就会访问http://localhost:8013/api/appraisal-classification/list这个地址,是一个get请求,返回的数据必须如下图所示,否则框架会找不到对应的数据。

也就是最外层是code,data和message属性,这个message属性就是我们做各种操作的提示信息,data下有current,orders,pages,size和total属性,这五个是有关分页和排序的数据,再加上一个records才是我们查出来数据库的内容。

这些属性少了都会有问题。

当你点击搜索的时候,也会走这个地址,如果搜索的输入框有内容的话,会在原来的参数基础上加上输入框的内容,如果日期搜索有内容的话,也是这样。

所以如果想完成搜索功能,后端需要接收一个input框的内容,然后可以做模糊查询之类的,还需要接收startTimeendTime

crudMethod存的是我们引入的api中的内容,相当于是让crud这个框架知道这个页面用的是什么api,另外你自己想用某个api的数据,也可以通过引入的名字来调用。

它的下面是optShow属性,会发现里面有五个属性为true,这个是控制第二排四个按钮,和重置按钮的显示,比如有的时候我们不需要导出功能,就需要让download属性为false,这个时候你就会发现页面上没有导出按钮了,其它也是同理。

这个时候我们就要聊聊api中的adddeledit函数了。

这三个函数的名字是固定的,甚至连参数的格式也是固定的。

当点击页面上的添加按钮并提交后,会调用这里的add函数,参数是form表单的数据。
当点击页面上的删除按钮,或勾选了很多进行删除,都会调用del函数,给后端发送一个list(不是json),只是一个list,类似[1,2,3],里面存的是选中行的id。
当点击页面上的修改按钮并提交后,会调用edit函数,参数是form表单的数据外加编辑的那一行table的数据。

这样的话,整个页面我就算是讲完了,剩下的我感觉自己摸索就可以了。

component

components文件夹下有很多的内容,比如面包屑,导航栏,图标,日期搜索框等。

而对我们最重要的,就是Crud这个文件夹内的内容了,所以今天就只讲讲这一块。

crud

这个文件夹下,我就说crud.jsCRUD.operation.vue两个内容,把这两个内容了解一些,其它的内容也可以理解一些了,另外就是其它的内容我研究的也不多,希望各位能多出一些其它的内容来教教我,感激不尽。

CRUD.operation.vue

这就是它的能力范围,我为什么要说这个呢? 因为有的时候,我们不见得就想用它的按钮,比如我们想加个批量修改的按钮,就需要自己在CRUD.operation的基础上进行一个封装才可以。

点开之后是这样一堆的东西,上面写的是四个按钮,可以看到为什么我们在页面中optShow属性中,通过对download属性设置false,可以让导出按钮消失,就是这个v-if设置的,同样的你想让其它button消失,也可以进行设置。

然后你会发现下面有较为复杂的js代码,其实你没必要看懂的,也不太需要。

如果你想在导出的右边再加一个按钮,只需要复制一下导出这个按钮,然后改一下名字,然后把click事件改一下,完成自己想要的功能就可以了。

crud.js
添加按钮的执行过程

我们可以通过CRUD组件来打开crud.js的大门,页面往往有四个按钮,我带你分析一下新增按钮,可以发现click绑定的是crud的toAdd函数。

我们找到这个函数,会发现它的作用是启动添加
首先是调用了resetForm()函数,清空一下表单,接下来是关于crud钩子的判断,然后比较重要的是设置了一下add的状态,为CRUD.STATUS.PREPARED,这个状态代表现在是启动添加,。

你找一下这个状态,会发现它的值为1

你还记得弹出框有个通过crud.status.cu > 0来控制对话框的显示和关闭吗?而我们通过找到cu,发现它是通过判断按钮的值来返回的,此时cu的值就是1,那么对话框就会弹出来。

也就是当你点击新增按钮的时候,调用了toAdd方法,这个方法设置了crud.add=1,而cu属性会获取这个1,对话框通过cu属性>0来显示。

接下来我们再看看toAdd函数第一行调用的resetForm函数,可以看到第一行它就去找form节点,如果你的对话框的ref不是form的话,就找不到了。

此时用户应该在填写表单,如果它点击了取消,会调用cancelCU函数,如果点击确定会调用submitCU函数。

这个cancelCU里进行了一大堆,其实就是维护状态,把他们的status都变成0,也就是CRUD.STATUS.NORMAL,然后再resetForm,把表单清除一下。

按钮的操作中主要靠这个状态来做操作。

submitCU重要的是下面,它会通过校验是哪个按钮是PREPARED状态,也就是正在写表单的状态,那就说明哪个该提交了,那么它就会走crud.doAdd()

我们点进去发现它是执行添加函数,可以看到函数内第三行是给add赋值了一个PROCESSING状态
按钮其实就是三个状态:NORMALPREPAREDPROCESSING,第一个代表无操作,第二个代表这个按钮被点击了,用户正在写对话框中的数据,属于占用状态,第三个就代表用户已经写好了对话框,点击提交,是提交阶段。

紧接着你就发现它调用了Method.add,也就是我们页面中引入的api文件中的add函数,然后把form表单中的数据存进去。

因为已经开始调用api了,也就说明已经提交上去了,如果提交成功,就把add的状态重新变为NORMAL,也就是0,那么对话框就会消失,如果提交报错,就会走catch,把add的状态重新设置为PREPARED,也就是1,对话框不会消失,此时你可以查看错误重新提交。

添加过程就结束了。

各种常用的函数

接下来就是在crud文件的闲逛了。

这个title返回的数据就是页面中crud.status.title获取到的,如果判断是新增按钮,就加新增两个字,如果判断是编辑按钮,就加编辑两个字。

内部还有一个可以获取query参数的函数,通过传名字就可以获得对应的值。

看一下刷新函数吧,点击重置按钮,或者新增,删除,修改,搜索也都会引起刷新。

之前说后端参数的时候,为什么说返回的格式必须要那样返回,是因为后端在获取参数的时候都是写好的。看我红框的这一条,crud.data就是我们的页面中table的数据,当没有页数的时候,它获取的是res.data,当有页数的时候它获取的是res.data.records,也就是说,当你没有分页的时候,你返回的格式应该是res.data,data下是你的数据列表,当你有分页的时候,就要再加一个records来存你的数据列表。

下面这个是获取查询的参数,input框的就不说了,主要看createTime那里,它会获取这个项为createTime,也就是页面上的query.creatTime是不能改的,获取到了之后,对这个time进行了一些转换,然后通过crud.query的参数来存一下,这个就是发给后端的参数名,可见,也是写死的,不过可以通过修改这里来改变名字。

在这个文件的最下面,会发现有一个CRUD钩子,这个是很好用的。

它就是crud的生命周期,比如你想在crud的Refresh(刷新)函数调用之前,也就是每次重新加载数据之前,想做一些事情,就可以在这里写。

又比如你想在点击编辑按钮之前做一些事情,也可以找到对应的钩子去写语句就可以了。

最后想说说casbin

casbin可以实现对某个角色进行api级的控制,可以让某个角色去访问某些api,或者去禁止某些api。

你下载el-admin,会发现它有一个casbin_rule数据表,里面存的是一些策略,v0下的1代表是sys_role表id=1的角色,v1是api地址,v2是GET,也就是当用户角色id=1的时候,就运行它访问/api/activity请求,类型为GET。

比如说你想限制某些角色的能力,就可以在这里进行控制。

那么我们一个一个的加,肯定不现实,前端有方式去做。

添加菜单的时候,会发现它有一个请求方式请求路由,这个对标的是我们刚进入这个页面的那个table的查询接口。
当你写上/api/activity GET的时候,当你为某个角色分配这个菜单,它就会在casbin_rule这个表格里添加对应的数据。

那么同样的,每个菜单下还有很多的按钮,每一个按钮都有对应的地址,就可以点击按钮新建了,也有这个请求方式和请求路由,按钮新建之后并不会在页面上显示,它只是一个为casbin权限控制作说明而已。

这样当你对角色1分配这个菜单之后,这个菜单对应的接口对应这个角色会添加到casbin里,然后这个角色调用这些已经被允许的接口才会被通过,否则显示权限不足。

需要注意的是,它同样需要后端的配合,如果后端没有搭建casbin的话,依然没有作用。

后端

这一篇内容写了很久,起初是想前后端都写,但是后来想想,后端好像没什么可写的,既然都接触到这个程度了,不至于连接口是什么都不清楚。

我感觉前端摸清楚了之后,后端并不怎么复杂。 就是一个不断的调接口的过程,知识是相对比较固定的,如果你是Java语言,大可以把el-admin的后端下载下来,然后在其基础上进行删改,添加。

如果你是其它语言,可以先找一个框架,然后找一个框架好用的脚手架,在这个脚手架的基础上写接口来返回数据就可以了。

基本上获取的时候,都是这个参数,Current,Size,Orders前端会自动返回给你,Content是搜索框的内容,StartTime和EndTime是时间搜索框的内容。

如果有哪些地方我没讲明白的,或者忽略了,忘记讲了,欢迎找我讨论,或者下面评论,我会回复或进行更新。

感谢 & 参考资料

博客:

在写文件架构的时候,部分内容参考了下面这个博客。
el-admin框架简单解析-快速入门(前端部分)


欢迎评论区讨论,或指出问题。 如果觉得写的不错,欢迎点赞,转发,收藏。

  • 39
    点赞
  • 118
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论
el-upload 是 Element UI 中负责文件上传的组件,本文将基于实际项目中的场景,进行 el-upload 的实战讲解。 场景:在一个类似于头像上传的场景中,需要上传图片,并且需要在上传完成后立即在页面上显示上传的图片。 一、组件引入 首先,为了使用 el-upload 组件,我们需要在代码中引入组件。在文件开头 import Element UI: ```js import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css' Vue.use(ElementUI) ``` 然后在页面上使用 el-upload 组件,代码如下: ```html <template> <el-upload action="上传图片的接口地址" :auto-upload="false" :file-list="fileList" :before-upload="beforeUpload" :on-success="uploadSuccess" :on-error="uploadError" list-type="picture-card"> <i class="el-icon-plus"></i> <div class="el-upload__text">上传头像</div> <div slot="tip" class="el-upload__tip"> 只能上传jpg/png文件,且不超过500kb </div> </el-upload> <div class="avatar-preview"> <img :src="avatarUrl" v-show="avatarUrl" alt=""> </div> </template> ``` 以上代码中: - `action` 属性指定上传图片的接口地址; - `:auto-upload="false"` 属性表示禁止自动上传; - `:file-list="fileList"` 绑定一个数组,用于保存上传成功的文件信息; - `:before-upload="beforeUpload"` 方法指定在上传之前的校验,可用于限制上传文件类型及大小; - `:on-success="uploadSuccess"` 方法用于在上传成功后的处理,最终将图片在页面上显示; - `:on-error="uploadError"` 方法用于在上传失败后的处理; - `list-type="picture-card"` 属性表示以卡片的形式显示上传的图片。 二、上传前的校验 我们需要在上传之前对图片进行校验,限制上传文件类型及大小,防止上传过程中出现不必要的错误。代码如下: ```js beforeUpload(file) { const fileType = file.type.split('/')[1] if (fileType !== 'jpg' && fileType !== 'png') { this.$message.error('只能上传jpg/png文件!') return false } const fileSize = file.size / 1024 if (fileSize > 500) { this.$message.error('上传文件大小不能超过500kb!') return false } return true } ``` 以上代码中: - `file.type.split('/')[1]` 通过切割文件类型获取文件后缀; - `this.$message.error` Element UI 中的消息提示组件,用于给出用户友好的提示信息。 - `return true` 表示通过前置校验,可以进行上传。 三、上传成功后的处理 在 el-upload 中,上传成功后可以通过 `:on-success` 方法指定一个方法进行处理。根据项目需求,我们需要将上传的图片在页面上显示出来,代码如下: ```js uploadSuccess(response, file, fileList) { this.fileList.push({ name: file.name, url: response.data.url }) this.avatarUrl = response.data.url } ``` 在上传成功后,我们需要将上传成功的文件信息保存到 `fileList` 中。在 `this.avatarUrl` 中保存成功上传的图片地址,从而在页面上显示出来。 四、上传失败后的处理 与上传成功类似,上传失败后也可以通过 `:on-error` 方法进行处理。一般情况下,上传失败往往是由于网络原因或者服务端问题导致,我们需要给用户一个友好的提示信息,代码如下: ```js uploadError(error, file, fileList) { this.$message.error('上传失败,请重试!') } ``` 以上就是一个 el-upload 的实战演练。总的来说,el-upload 这个组件非常易于使用,只需要掌握三个方法(before-upload,on-success,on-error)就可以完成我们的需求。同时,Element UI 中还提供了其他的上传组件,如 el-dragger、el-cascader 等,可根据具体项目需求进行选择。
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jacob_云飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值