目录
我们知道运维开发更的是偏向后台管理方面,所以本章开始以Element UI为例子,展示数据的增删除改查,进行讲解。
后端我使用的是PHP的web框架thinkphp,前端使用vue+vue router+axios+element ui 进行操作
一、需求
1.1 对后台数据进行增删除改查操作
某网站只是简单的宣传网站,要求工作人员可以对显示的数据进行增删改操作。查询默认是全部。使用element组件实现
效果图,如下图所示:
1.2 对某行的操作
- 编辑功能。点某行后面的“编辑”按钮可以对本行进行编辑,编辑马上变成“保存”,并且数据显示可编辑状态(图片ID是自动生成的,所以不用)
注:图片ID是网站自动生成添加上去的,使用UUID唯一ID,我这里方便,示例先用简单的编写。
2. 保存功能。修改完成后,点“保存”即完成保存,如果不想修改,那就刷新就行了。
3.删除功能。点“删除”,实现某行被删除。
4.增加行功能。点最下面的“添加”按钮实现添加功能,如下图所示:
1.3 批量选择和删除操作
1.全选功能。当点在“全选”旁边打勾,并在本底部显示删除功能和取消删除选择功能。如下图所示:
2.多选删除。当在某行前面打勾,底部也行显示删除和取消选择。
1.4 分页功能
因为数据比较多,所以提供分页功能。效果如下图所示:
显示数据有多少页,每页可以显示多少条,默认为5条。可以选择前往第几面。
二、关于数据显示
要显示数据,我们可以使用element中的table表格功能。里面例子中有添加编辑功能的。
使用<<el-table>标签中的 data属性绑定数据即可。根据最下面的参数说明,知道这个是一个数组。
因为前后端分离,我们可以使用axios向后端提交get请求,后端返回json数据,转换成数组即可。因为一打开主页就显示数据,我们可以使用 vue的 mounted() 方法。
后端返回的json数据保存起来,既然是数据可以放在vue中的data,我这里在data建立一个info:null 属性来接收。这样就要以填写 table表的data属性了。
<el-table :data="info" ... >
三、 关于行操作
3.1 行显示
3.1.1 行每列数据显示
在element的基础表格例子中已经有说明:
当
el-table
元素中注入data
对象数组后,在el-table-column
中用prop
属性来对应对象中的键名即可填入数据,用label
属性来定义表格的列名。可以使用width
属性来定义列宽。
这样基础表就完成了。
我这里几列prop为:
多选框:可以使用element table的 <el-table-column type="selection">标签实现
序列号:可以使用element table的 <el-table-column type="index"> 标签实现的。
picid:图片的id。axios请求后端返回的数据。
picurl:图片的url地址,用来显示图片的。axios请求后端返回的数据。
lable:图片名字。axios请求后端返回的数据。
describe:图片说明。axios请求后端返回的数据。
isSet:行row是否被选择,后面用到,并非放在列显示,而是当属性使用。axios请求后端返回的数据。
注:我们的data的数组,会被放在element插槽的row属性中。
3.1.2 文本数据显示
普通数据,即文本类的数据,比如picid、lable、describe可以直接使用html的<span>
3.1.3 图片类显示
我们可以使用element中的图片功能。<el-image>使用它的src属性,这样就可以与vue中的数据交互的
:src="scope.row.picurl
当然你使用普通的img也可以,使用:src也一样的。
3.1.4 关于element列域插槽slot
如果在列中插入自己定义的标签,在标签中要使用列的prop定义属性,怎办?比如下面的:
<el-table-column prop="picid" label="图片ID" width="80">
如果写成
<el-table-column prop="picid" label="图片ID" width="80">
<span>{{ picid }}</span>
</el-table-column>
这样是不行的,这样变成了,使用vue data中的 picid属性了,我们要的是此列中的picid属性。
element也帮我们想到了,可以使用slot插槽的方式,介绍如下:
这样我们可以写成这样
<el-table-column prop="picid" label="图片ID" width="80">
<template v-slot="scope">
<span>{{ scope.row.picid }}</span>
</template>
</el-table-column>
v-slot中使用的是插槽域slot-scope ,声明了被接收的 prop 对象会作为 scope 变量存在于 <template>
作用域中。这个变量名字可以随便起,不影响,要有意义就行。
这里scope表示element的table表格,prop数据是放在名为row的成员中。
PS:上面学过slot也说了,如果要使用slot要么就直接在自定义组件中写,要么就在模板<template>中写,这里使用的是模板。
3.2 行编辑功能
在行添加编辑功能,只要添加一个空的列,在列中插入一个按钮并命名为“编辑”。这里编辑涉及编辑前,有编辑状态。
3.2.1 不可编辑状态
没点编辑关数据为显示状态,是不可以编辑的,如下图所示:
既然它不可以编辑,我们可以在表格中列中插入html的<span>标签,作为显示。当然其它显示标签也行。
3.2.2 文件数据编辑状态
点了某行的“编辑”,即进行可编辑状态。
如何把显示的变成可编辑的呢。可以把这个的显示标签变成可编辑的文本 <input type="text">即可,这样要写一堆js脚本。所以换成为具体列做添加一个属性如isSet表示是否可编辑,再结合vue的v-if判断语句来判断显示即可,这样就可以巧妙使用vue了。
如果是文本数据可以直接把<span>变成为intpu text类型就行了,我这里使用的是element的<el-input>标签。
例如:lable列:
<el-table-column prop="lable" label="图片名" width="100">
<template v-slot="scope">
<span v-if="scope.row.isSet">
<el-input size="mini">
</el-input>
</span>
<span v-else>{{ scope.row.lable }}</span>
</template>
</el-table-column>
3.2.3 图片类编辑状态
图片类编辑,我们可以使用element的上传功能。中用户头像
3.2.4 编辑功能数据放回编辑框中
当点“编辑”的时候数据要放回编辑框中,怎搞?
上面说了,element给我们一个名为row的行属性,我们可以在自己的vue data中添加一个字段专门放这被选择的行数据,比如“rowSelect”,利用vue的双向绑定功能就可以实现填回去。
如上面的lable代码修改为:
<el-input size="mini" placeholder="请输入内容" v-model="rowSelect.lable">
</el-input>
3.2.5 编辑变保存
编辑按键变保存按钮,这个也简单,也是利用判断isSet字段。代码如下:
<el-table-column label="操作" width="">
<template v-slot="scope">
<span v-if="scope.row.isSet" class="el-tag el-tag--success el-tag--small" style="cursor: pointer;"
@click.stop="saveRow(scope.row,scope.$index)">
保存
</span>
<span v-else class="el-tag el-tag--primary el-tag--small" style="cursor: pointer;"
@click="editRow(scope.row,scope.$index)">
编辑
</span>
</template>
</el-table-column>
3.3 行保存功能
3.3.1 提交删除请求
要实现保存,使用axios的PUT请求即可,我使用的是restful风格
以对用户user操作为例子
在Restful之前的操作:
http://127.0.0.1/user/query/1 GET 根据用户id查询用户数据
http://127.0.0.1/user/save POST 新增用户
http://127.0.0.1/user/update POST 修改用户信息
http://127.0.0.1/user/delete GET/POST 删除用户信息RESTful用法:
http://127.0.0.1/user/1 GET 根据用户id查询用户数据
http://127.0.0.1/user POST 新增用户
http://127.0.0.1/user PUT 修改用户信息
http://127.0.0.1/user DELETE 删除用户信息
3.3.2 vue data重新查询
提交更新后,因为我使用的是mounted,只执行一次,所以还得手工执行一次请求。
3.4 行删除功能
3.4.1 从数据库删除
要实现删除某行,使用axios的delete即可,
3.4.2 从vue显示数据中删除
使用axios提交delete删除,只是在数据库中删除。还有显示数据中删除才行,因为开始使用的是mounted挂载方式,只执行一次。当删除了数据之后,还要手工在data中进行删除,我这使用的是info
我们知道在数组中删除一个元素很简单使用splice方法就行了
this.info.splice(index, 1);
3.5 行添加功能
因为我使用的是mounted,只执行一次,得手工插入一条空数据,再进行编辑即可,可以在vue中添加一条行对象,把数据设置为空
let emptyRow = {
picurl: null,
lable: '',
describe: '',
// 这个一定要设置
isSet: 1
}
this.info.push(emptyRow);
this.rowSelect = emptyRow;
四、批量操作之多选
4.1 多选解释
批量操的多选,在element中有多选例子,官方解释为:
实现多选非常简单: 手动添加一个
el-table-column
,设type
属性为selection
即可;默认情况下若内容过多会折行显示,若需要单行显示可以使用show-overflow-tooltip
属性,它接受一个Boolean
,为true
时多余的内容会在 hover 时以 tooltip 的形式显示出来。
与选择相关的事情有:
添加多选也简单,在<el-table>标签中添加 @selection-change="handleSelectionChange" 事情,再添加一个列 type为selection的列就行了
<el-table-column type="selection" width="80"></el-table-column>
4.2 在多选框后面添加“全选”字样
element默认的多选是没有“全选”字样的,如它的多选例子
如果我要在旁边添加一个“全选”的字样怎办?可以使用在样式中添加,代码如下:
/* /deep/ 深度选择器 有兴趣可以搜索一下 https://www.love85g.com/?p=1879*/
/deep/ .el-table__header-wrapper .el-checkbox__input::after {
content: '全选';
position: absolute;
margin-left: 5px;
}
这样就显示全选了。
4.3 全选和取消全选功能实现
4.3.1 全选功能
element已经自带有全选功能,这样不用说了。
4.3.2 取消全选
取消全选功能也有自带的方法
实现代码
可以在element <el-table>标签外添加一个按钮,并指定方法。可以按照官方element多选例子做参考,进行编写。
<el-button type="primary" @click="toggleSelection()">取消选择</el-button>
toggleSelection方法如下:
toggleSelection(rows) {
if (rows) {
rows.forEach(row => {
this.$refs.multipleTable.toggleRowSelection(row);
});
} else {
this.$refs.multipleTable.clearSelection();
}
}
ps:这里<el-table>需要添加一个ref属性,并指定名字。
ref="multipleTable"
五、批量操作之删除
批量操作删除也是分2个部分,一个是提交删除,一个是在data 的info数据中进行删除
5.1 为每行添加索引
在默认中,行索引是不放在element被选择的行中的。可以在<el-table>标签中添加ow-class-name并指定一个方法,我的为:
这里的string表示方法名,也可以直接写函数,我这里写方法名。
:row-class-name="tableRowClassName"
tableRowClassName方法实现如下:
// eslint-disable-next-line no-unused-vars
tableRowClassName(row, index) {
// 给每条数据添加一个索引,方便批量删除
row.row.index = row.rowIndex;
},
5.2 使用http delete方法请求删除
我使用的是thinkphp支持提交数组方式删除,所以我就直接把先选择的列变成数组方式,再转为json,用axios的delete方法进行提交删除 。
5.3 删除vue中的info成员
因为我使用的是mounted挂载方式,只执行一次,把数据放在data的info中,所以info得清除这些数据。
js中要从数组中删除2个成员,不能使用splice方法,此方法只适合删除1条,或者下标号相邻数据。使用数组的splice方法进行删除多个元素,因为会变的,会出问题。删除一个元素数组的下标就会发生变化,这样就会产生错乱。要用Set集合的delete方法进行删除。可以把数组直接转为set。Set
函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数,用来初始化。实现代码如下:
let rows = this.multipleSelection
//放删除的id
let selPicids = [];
if (rows.length === 1) {
alert("你只选择一条数据!")
this.deleteRow(rows[0], rows[0].index);
}
/*
* 注意,这里不能直接在for of中,使用数组的splice方法进行删除多个元素,因为会变的,会出问题。
* 因为删除一个元素数组的下标就会发生变化,这样就会产生错乱
* 要用Set集合的delete方法进行删除
* */
let mySet = new Set(this.info)
for (let row of rows) {
selPicids.push(row.picid);
//删除vue展示
mySet.delete(row);
六、分页功能
elemnet本身也自带有分页功能,直接拿来用就行了。我的分面功能代码如下:
<div>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes=[5,10,20,30,50]
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
hide-on-single-page
:total="pageTotal"
>
</el-pagination>
</div>
上面currentPage(当前页)、pageSize(每页条数)、pageTotal(总页数)为vue data中的字段:
data() {
return {
pageTotal: 7,
pageCount: 10,
pageSize: 5,
currentPage: 1,
...
}
每点一页,我就使用axios向后台请求一下。
上面对应的方法为:
handleSizeChange(val) {
//每页 val 条
this.pageSize = val;
this.listDataByPage();
},
handleCurrentChange(val) {
// 当前页: val
//alert(val);
this.currentPage = val;
this.listDataByPage();
},
listDataByPage() {
axios
//默认第1页,5条,可以修改一下currentPage 和 pageSize 的值
.get('/vue?page=' + this.currentPage + '&pageSize=' + this.pageSize)
.then(
response => {
let res = response.data;
this.resData = res;
this.pageTotal = this.resData['list']['total'];
this.pageCount = this.resData['list']['last_page'];
this.info = res['list']['data'];
return this.info;
}
);
}
上面.get中的 page 和 pageSize 是后台请求的参数,是提交当前页和每页显示的条数,这样就可以在后台计算有多少页了,返回第几页的数据。
这样整个项目需求就分析完了,后面我将讲环境的搭建、后端thinkphp代码、vue的完成代码。