vue2项目中表格的增删查改

我们在项目中经常会用到对于表格的增删查改操作,以下使用vue2+elementui来实现表格的增删查改

表格的基本属性

基础表格如下:(其中需要注意的是当el-table元素中注入data对象数组后,在el-table-column中用prop属性来对应对象中的键名即可填入数据用label属性来定义表格的列名。可以使用width属性来定义列宽。)

 <template>
    <el-table
      :data="tableData"
      style="width: 100%">
      <el-table-column
        prop="date"
        label="日期"
        width="180">
      </el-table-column>
      <el-table-column
        prop="name"
        label="姓名"
        width="180">
      </el-table-column>
      <el-table-column
        prop="address"
        label="地址">
      </el-table-column>
    </el-table>
  </template>

  <script>
    export default {
      data() {
        return {
          tableData: [{
            date: '2016-05-02',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1518 弄'
          }, {
            date: '2016-05-04',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1517 弄'
          }, {
            date: '2016-05-01',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1519 弄'
          }, {
            date: '2016-05-03',
            name: '王小虎',
            address: '上海市普陀区金沙江路 1516 弄'
          }]
        }
      }
    }
  </script>

使用带斑马纹的表格,可以更容易区分出不同行的数据。

stripe属性可以创建带斑马纹的表格。它接受一个Boolean,默认为false,设置为true即为启用。

带边框表格:

默认情况下,Table 组件是不具有竖直方向的边框的,如果需要,可以使用border属性,它接受一个Boolean,设置为true即可启用。

带状态表格

可以通过指定 Table 组件的 row-class-name 属性来为 Table 中的某一行添加 class,表明该行处于某种状态。

<template>
  <el-table
    :data="tableData"
    style="width: 100%"
    :row-class-name="tableRowClassName">
    <el-table-column
      prop="date"
      label="日期"
      width="180">
    </el-table-column>
    <el-table-column
      prop="name"
      label="姓名"
      width="180">
    </el-table-column>
    <el-table-column
      prop="address"
      label="地址">
    </el-table-column>
  </el-table>
</template>

<style>
  .el-table .warning-row {
    background: oldlace;
  }

  .el-table .success-row {
    background: #f0f9eb;
  }
</style>

<script>
  export default {
    methods: {
      tableRowClassName({row, rowIndex}) {
        if (rowIndex === 1) {
          return 'warning-row';
        } else if (rowIndex === 3) {
          return 'success-row';
        }
        return '';
      }
    },
    data() {
      return {
        tableData: [{
          date: '2016-05-02',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄',
        }, {
          date: '2016-05-04',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄'
        }, {
          date: '2016-05-01',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄',
        }, {
          date: '2016-05-03',
          name: '王小虎',
          address: '上海市普陀区金沙江路 1518 弄'
        }]
      }
    }
  }
</script>

以上代码的效果是
在这里插入图片描述
具体的逻辑如下:(通过指定 Table 组件的 row-class-name 属性来为 Table 中的某一行添加 class,表明该行处于某种状态。下面这个函数传入的是一个对象,row表示的是每一行的数据信息,rowIndex表示的是索引下标。一下表示行标为1 的显示warning-row的style效果,行标为3的显示成功的效果)

 tableRowClassName({row, rowIndex}) {
        if (rowIndex === 1) {
          return 'warning-row';
        } else if (rowIndex === 3) {
          return 'success-row';
        }
        return '';
      }

我们可以在这里改需求,比如说如果想要奇数偶数页不同,我们可以改变函数

     tableRowClassName ({ row, rowIndex }) {
      if (rowIndex%2=== 0) {
         return 'warning-row';
       } else  {
       return 'success-row';
       }
       return '';
     }

再比如修改日期为具体某一天的颜色

    // 日期是五月一号的改颜色
      tableRowClassName ({ row, rowIndex }) {
       if (row.date=== '2016-05-01') {
        return 'warning-row';
       } else {
         return 'success-row';
       }
       return '';
     }

固定表头

只要在el-table元素中定义了height属性,即可实现固定表头的表格,而不需要额外的代码。

固定列

固定列需要使用fixed属性,它接受 Boolean 值或者leftright,表示左边固定还是右边固定。

固定列和表头可以同时使用,只需要将上述两个属性分别设置好即可。

排序

在列中设置sortable属性即可实现以该列为基准的排序,接受一个Boolean,默认为false。

筛选

在列中设置filters,filter-method属性即可开启该列的筛选,filters 是一个数组,filter-method是一个方法,它用于决定某些数据是否显示,会传入三个参数:value, row 和 column。

<template>
  <el-table
      :data="tableData"
        border
        :row-class-name="tableRowClassName"
        style="width: 100%">
        <!-- 其中这个prop一定要和下面tableData中的键保持一致 -->
        <el-table-column
          prop="date"
          label="日期"
          sortable
          width="180"
          :filters="[{ text: '2016-05-01', value: '2016-05-01' }, { text: '2016-05-02', value: '2016-05-02' }, { text: '2016-05-03', value: '2016-05-03' }, { text: '2016-05-04', value: '2016-05-04' }]"
          :filter-method="filterHandler">
        </el-table-column>
        <el-table-column
          prop="name"
          label="姓名"
          width="180">
        </el-table-column>
        <el-table-column
          prop="address"
          label="地址">
        </el-table-column>
           <el-table-column
            prop="tag"
            label="标签"
            :filters="tagFilter"
            :filter-method="filterHandler"
            filter-placement="bottom-end">
              <template slot-scope="scope">
              //对表格里面的数据进行处理的话需要用到template,对于这个数据我们是不方便自定义的,如果要对数据进行更多的自定义,我们就可以使用template;scope相当于是一整个数据对象
              //下面的意思是拿到的数据等于家,就显示primary这种样式,否则后面一种样式
          <el-tag
            :type="scope.row.tag === '家' ? 'primary' : 'success'"
            disable-transitions>{{ scope.row.tag }}</el-tag>
        </template>
          </el-table-column>
      </el-table>

</template>

<script>
export default {
  name: 'Navbar',
  data() {
    return {
       tableData: [{
        date: '2016-05-02',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1518 弄',
        tag: '家'
      }, {
        date: '2016-05-04',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1517 弄',
        tag: '公司'
      }, {
        date: '2016-05-01',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1519 弄',
        tag: '家'
      }, {
        date: '2016-05-03',
        name: '王小虎',
        address: '上海市普陀区金沙江路 1516 弄',
        tag: '公司'
      }]
    };
  },

  computed: {
    // filter中的数据是静态的,但是大多数项目中都是动态的,所以上面的filter需要进行变化
    tagFilter () {
      // 此时数据重复,需要进行降重处理
      // return this.tableData.map(v=>({ text: v.tag, value: v.tag }))

      let map = new Map();
      for (let item of this.tableData) {
        if (!map.has(item.tag)) {
          map.set(item.tag,item)
        }
      };
      // 但是当前map是一个二维数组,需要进行转换
      let data = [...map.values()]
      return data.map(v=>({ text: v.tag, value: v.tag }))
    }
  },
  methods: {
    // value代表的是当前的数据,row代表的是整个对象,column表示的是表格的特性(可以拿到某个属性的名字)
    filterHandler (value, row, column) {
      const property = column['property'];
      // 这个的意思就是从表格里面筛选出来和value相同的值
      return row[property] === value; 
      //  row[property]:就比如说我拿到tableData中的date ,即tableData[date]
    }
},
};
</script>

动态数据的增删查改

我们使用json-server模拟请求以及请求回来的过程。详情请看json-server的入门

  1. 拿到数据展示到页面
<template> 
  <el-table
        :data="tableData"
        border
        style="width: 100%">
        <!-- 其中这个prop一定要和下面tableData中的键保持一致 -->
           <el-table-column
            prop="title"
            label="文章标题"
            width="180"
           >
          </el-table-column>
           <el-table-column
            prop="user"
            label="姓名"
            width="180">
          </el-table-column>
        <el-table-column
          prop="date"
          label="日期"
          sortable
          width="180"
         >
        </el-table-column>
        <el-table-column
          prop="id"
          label="ID">
        </el-table-column>
           <el-table-column
              prop="check"
              label="状态">
            </el-table-column>
      </el-table>

</template>

<script>
import axios from 'axios';
export default {
  name: 'Navbar',
  data() {
    return {
      //动态数据需要对应传过来的键名
       tableData: []
    };
  },
  methods: {
  },
  created () {
    axios.get('http://localhost:3009/userList').then(res => {
      // this.tableData = res;
      console.log(res.data);
      this.tableData = res.data;
    })
    }
};
</script>

<style>
</style>

我们会发现没有状态的值,就算展示也不能直接展示布尔值,在这里我们可以用到标签

 <el-table-column
              prop="check"
              label="状态">
              <template slot-scope="scope">
          <el-tag
            :type="scope.row.check === 'false' ? 'primary' : 'success'"
            disable-transitions>{{ scope.row.check }}</el-tag>
        </template>
            </el-table-column>

接着要进行文本格式化,转化为用户能够识别的文字。这个文本格式化要借助过滤器,然后通过管道的思想把它加添加进去

 filters: {
    checkFilter (v) {
      switch (v) {
        case true:
          return '已发表'
        case false:
          return '未发表'
        default:
          return '未发表'
      }
    }
  },
<el-tag
            :type="scope.row.check ? 'success':'primary' "
            disable-transitions>{{ scope.row.check| checkFilter }}</el-tag>

在这里插入图片描述
最后的效果:
在这里插入图片描述
增加操作项(编辑和删除)

     <el-table-column label="操作">
        <template slot-scope="scope">
          <el-button
            size="mini"
            @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
          <el-button
            size="mini"
            type="danger"
            @click="handleDelete(scope.$index, scope.row)">删除</el-button>
        </template>
      </el-table-column>

我们将添加项放到最顶上

 <el-button
      type="success"
      round
      size="mini"
      @click="handleSet('add',null)"
    >增加</el-button>

但是这个时候出现了一个问题,vscode代码行会有很多红色的波浪行(原因是代码和vetur插件的格式不对应所以导致出现红色波浪线)解决办法有:1.在template下用一个div标签包裹住我们所写的代码,或者用el-card包裹住也可以。 2.设置vetur,将以下三个选项的勾选全部取消掉

在这里插入图片描述
但是,事实证明虽然没有红色波浪线了,但是运行的时候仍然会报错。所以最好还是采用第一种方法解决。

添加和编辑

首先可以先捋顺一下添加和编辑的思路,添加的话,弹出的对话框中的数据都是空的,而编辑的话里面则是都有之前的数据的
所以我们在添加点击事件的时候

 <!-- 添加 -->
   <el-button
      type="success"
      round
      size="mini"
      @click="handleSet('add',null)"
    >增加</el-button>
   <!-- 编辑 -->
     <el-button
            size="mini"
            @click="handleSet('update',row)"
       >编辑</el-button>

添加弹框(思路是:如果先通过三元运算符来判断是添加还是编辑,如果是添加的话就需要弹出来的框里面没有内容,如果是编辑的话就显示之前的内容;visible.sync这个是用来判断这个对话框是否弹出,默认不弹出false,触发了点击事件以后就将其变为true。其中还form表示的是整个弹框对象,当然里面有哪些内容还是要取决于tableData,比如table里面有标题title,姓名name,日期date,id,check状态等这些变量,那么我们的form里面就要在这个变量范围内,本次用的是form.user,form.title,form.date,form.check)

    <el-dialog
      :title="state=='add'?'添加':'编辑'"
      :visible.sync="dialogTableVisible"
    >
      <!-- 其中下面这个form代表的是整个弹框对象 -->
      <el-form :model="form">
        <el-form-item label="发布作者">
          <el-input v-model="form.user"></el-input>
        </el-form-item>

        <el-form-item label="文章标题">
          <el-input v-model="form.title"></el-input>
        </el-form-item>

        <el-form-item label="日期">
          <el-date-picker
            v-model="form.date"
            type="date"
            placeholder="选择日期"
          >
          </el-date-picker>
        </el-form-item>

        <el-form-item label="状态">
          <el-switch
            v-model="form.check"
            active-color="#13ce66"
            inactive-color="#ff4949"
          >
          </el-switch>
        </el-form-item>
      </el-form>
      <div
        slot="footer"
        class="dialog-footer"
      >
        <el-button @click="dialogTableVisible = false">取 消</el-button>
        <el-button
          type="primary"
          @click="dialogTableVisible = false"
        >确 定</el-button>
      </div>
    </el-dialog>

其中点击事件中,我们先要看是哪种状态,我们要把是add还是update传入到我们的state中,来判断到底是要添加还是编辑,接着将弹窗状态变为true

 methods: {
    handleSet (type, row) { //设置数据
      this.state = type;
      this.dialogTableVisible = true; //弹框的状态
    }
  },

结果为:点击添加,添加的弹窗如下;点击编辑,编辑的弹窗也如下(我们可以看到编辑的弹窗应该要有之前原本的内容,但是现在还没有加进来)
在这里插入图片描述
在这里插入图片描述
所以我们要在点击事件中,要判断类型,如果是添加则form的值为空,如果是编辑则form的值为row,见下面代码的最后一行

   handleSet (type, row) { //设置数据
      this.state = type;
      this.dialogTableVisible = true; //弹框的状态
      type == 'add' ? this.form = {} : this.form = row;
    }

此时我们再试一次:
请添加图片描述

另外我们还可以看一下状态,此时未发表的状态是红色按钮,已发表的是绿色按钮。
请添加图片描述
但是此时还有一个bug(当我们修改了编辑中的日期,我们会发现表格中的日期会变成undefined,为什么会这样呢?原因在于这一块涉及到了深浅拷贝,简单来讲就是B复制了A,修改A时,如果B发生了变化就是浅拷贝,如果没有变化就是深拷贝)
请添加图片描述
解决办法:加扩展运算符扩展运算符是深拷贝还是浅拷贝?

handleSet (type, row) { //设置数据
      this.state = type;
      this.dialogTableVisible = true; //弹框的状态
      type == 'add' ? this.form = {} : this.form = { ...row };
    }

然后我们可以进行添加或者编辑操作了,但是现在我们的添加和编辑是同一个,那么到底是放到添加还是编辑里面呢?接下来就聊一聊弹框中数据的处理,这就是弹框中“确定”的处理。针对编辑和添加共用一个弹框的处理。
为“确定”按钮添加点击事件

<el-button
          type="primary"
          @click="updateData()"
        >确 定</el-button>

我们可以通过接口文档,数据的添加是post请求,数据的编辑是put请求,

  async updateData () {  //提交(可能是编辑的,也有可能是添加的)
      let method = this.state == 'add' ? 'post' : 'put';  //判断状态,如果是添加就是post,否则就是put
      let res = await axios({  //在里面要发送请求,拿到具体的数据,里面包含以下几种
        method: method,  //请求的类型,如果是添加就是post,编辑就是put
        url:   'data/${this.state}', //后面的值不确定是add还是update,所以可以通过${this.state}来获取
        data: this.form          //具体的数据对象
      })
    }
    this.userList();  //写完以后再次调用数据的查询

在这里插入图片描述
我们会发现上面新增的时间出现问题,所以我们需要进行时间的转换,在过滤器filters中写

 dateFilter (v) {
      let d = new Date(v);
      let timer = d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + (d.getDate());
      return timer;
    }

然后在日期上面添加一个template

 <el-table-column
        prop="date"
        label="日期"
        sortable
        width="180"
      >
        <template slot-scope={row}>
          {{ row.date |dateFilter}}
        </template>
      </el-table-column>

结果如下:

在这里插入图片描述

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

纵有千堆雪与长街

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

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

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

打赏作者

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

抵扣说明:

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

余额充值