天天看点

hualinux 进阶 vue 5.1:用Element实现增删改查(一)需求及分析

目录

​​一、需求​​

​​1.1 对后台数据进行增删除改查操作​​

​​1.2 对某行的操作​​

​​1.3 批量选择和删除操作​​

​​1.4 分页功能​​

​​二、关于数据显示​​

​​三、 关于行操作​​

​​3.1 行显示​​

​​3.1.1 行每列数据显示​​

​​3.1.2 文本数据显示​​

​​3.1.3 图片类显示​​

​​3.1.4 关于element列域插槽slot​​

​​3.2 行编辑功能​​

​​3.2.1 不可编辑状态​​

​​3.2.2 文件数据编辑状态​​

​​3.2.3 图片类编辑状态​​

​​3.2.4 编辑功能数据放回编辑框中​​

​​3.2.5 编辑变保存​​

​​3.3 行保存功能​​

​​3.3.1 提交删除请求​​

​​3.3.2 vue data重新查询​​

​​3.4 行删除功能​​

​​3.4.1 从数据库删除​​

​​3.4.2 从vue显示数据中删除​​

​​3.5 行添加功能​​

​​四、批量操作之多选​​

​​4.1 多选解释​​

​​4.2 在多选框后面添加“全选”字样​​

​​4.3 全选和取消全选功能实现​​

​​4.3.1 全选功能​​

​​4.3.2 取消全选​​

​​五、批量操作之删除​​

​​5.1 为每行添加索引​​

​​5.2 使用http delete方法请求删除​​

​​5.3 删除vue中的info成员​​

​​六、分页功能​​

我们知道运维开发更的是偏向后台管理方面,所以本章开始以Element UI为例子,展示数据的增删除改查,进行讲解。

后端我使用的是PHP的web框架thinkphp,前端使用vue+vue router+axios+element ui 进行操作

一、需求

1.1 对后台数据进行增删除改查操作

某网站只是简单的宣传网站,要求工作人员可以对显示的数据进行增删改操作。查询默认是全部。使用element组件实现

效果图,如下图所示:

hualinux 进阶 vue 5.1:用Element实现增删改查(一)需求及分析

1.2 对某行的操作

  1. 编辑功能。点某行后面的“编辑”按钮可以对本行进行编辑,编辑马上变成“保存”,并且数据显示可编辑状态(图片ID是自动生成的,所以不用)
hualinux 进阶 vue 5.1:用Element实现增删改查(一)需求及分析

注:图片ID是网站自动生成添加上去的,使用UUID唯一ID,我这里方便,示例先用简单的编写。

2. 保存功能。修改完成后,点“保存”即完成保存,如果不想修改,那就刷新就行了。

3.删除功能。点“删除”,实现某行被删除。

4.增加行功能。点最下面的“添加”按钮实现添加功能,如下图所示:

hualinux 进阶 vue 5.1:用Element实现增删改查(一)需求及分析

1.3 批量选择和删除操作

1.全选功能。当点在“全选”旁边打勾,并在本底部显示删除功能和取消删除选择功能。如下图所示:
hualinux 进阶 vue 5.1:用Element实现增删改查(一)需求及分析
2.多选删除。当在某行前面打勾,底部也行显示删除和取消选择。

1.4 分页功能

因为数据比较多,所以提供分页功能。效果如下图所示:

hualinux 进阶 vue 5.1:用Element实现增删改查(一)需求及分析

显示数据有多少页,每页可以显示多少条,默认为5条。可以选择前往第几面。

二、关于数据显示

要显示数据,我们可以使用​​element中的table表格​​功能。里面例子中有添加编辑功能的。

使用<<el-table>标签中的 data属性绑定数据即可。根据最下面的参数说明,知道这个是一个数组。

hualinux 进阶 vue 5.1:用Element实现增删改查(一)需求及分析

因为前后端分离,我们可以使用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插槽的方式,介绍如下:

hualinux 进阶 vue 5.1:用Element实现增删改查(一)需求及分析

 这样我们可以写成这样

<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 不可编辑状态

没点编辑关数据为显示状态,是不可以编辑的,如下图所示:

hualinux 进阶 vue 5.1:用Element实现增删改查(一)需求及分析

既然它不可以编辑,我们可以在表格中列中插入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的上传​​功能。中用户头像

hualinux 进阶 vue 5.1:用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 的形式显示出来。

与选择相关的事情有:

hualinux 进阶 vue 5.1:用Element实现增删改查(一)需求及分析

添加多选也简单,在<el-table>标签中添加 @selection-change="handleSelectionChange" 事情,再添加一个列 type为selection的列就行了

<el-table-column type="selection" width="80"></el-table-column>      

4.2 在多选框后面添加“全选”字样

element默认的多选是没有“全选”字样的,如它的多选例子

hualinux 进阶 vue 5.1:用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 取消全选

取消全选功能也有自带的方法

hualinux 进阶 vue 5.1:用Element实现增删改查(一)需求及分析

实现代码

可以在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并指定一个方法,我的为:

hualinux 进阶 vue 5.1:用Element实现增删改查(一)需求及分析

这里的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;
            }
        );
  }