实现 element-ui 行拖拽+行内编辑

本文介绍了如何在Vue项目中结合Element-UI实现表格行的拖拽排序和行内编辑功能。使用sortablejs库实现拖拽,通过设置row-key和row-class-name确保正确排序。编辑功能通过深拷贝行数据并添加isSet属性来切换显示文本或输入框。详细代码示例展示了拖拽和编辑的完整实现过程。
摘要由CSDN通过智能技术生成

实现 element-ui 行拖拽+行内编辑

效果图
功能分为拖拽和编辑两部分

拖拽

使用 sortablejs 库,安装

npm install sortablejs --save

注意点
element table 务必指定 row-key,row-key 必须是唯一的,如ID,不然会出现排序不对的情况。
因为是指定列才可拖动,还要指定不可拖动的类名,el-table 中可通过 row-class-name 设置行的class

行内编辑

在 el-table 中,点击编辑时,先将当前行的数据进行一次深拷贝暂存起来,然后给这一行数据增加一个标识编辑的属性 isSet,通过改变 isSet 的值为 true 或 false,判断显示 input 或文字内容。

行内编辑参考:
elementUI table 点击编辑按钮进行编辑实现示例
vue elementui table 双击单元格实现编辑

拖拽功能参考:
sortablejs 官网
element-UI ,Table组件实现拖拽效果
Element-UI Table组件上添加列拖拽效果实现方法

下面是完整的 html 代码

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>实现 element-ui 行拖拽+行内编辑</title>
  <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
  <style>
    /* 拖拽 */
    .dragClass {
      background: rgba(65, 194, 26, 0.5) !important;
    }
    /* 停靠 */
    .ghostClass {
      background: rgba(108, 172, 245, 0.5) !important;
    }
    /* 选择 */
    .chosenClass:hover > td {
      background: rgba(245, 108, 108, 0.5) !important;
    }
  </style>
</head>
<body>
  <div id="app">
    <el-table
      row-key="id"
      :data="dataList"
      :row-class-name="tableRowClassName"
      style="width: 100%"
      size="medium"
    >
      <el-table-column prop="sort" label="重排" width="100">
        <el-button class="move" icon="el-icon-sort"></el-button>
      </el-table-column>
      <el-table-column type="index"></el-table-column>
      <el-table-column
        v-for="v in columns"
        :prop="v.field"
        :key="v.id"
        :label="v.title"
        :width="v.width"
      >
        <template slot-scope="scope">
          <span v-if="scope.row.isSet">
            <el-input
              placeholder="请输入内容"
              v-model="selectRow[v.field]"
            >
            </el-input>
          </span>
          <span v-else>{{ scope.row[v.field] }}</span>
        </template>
      </el-table-column>
      <el-table-column label="操作" width="200">
        <template slot-scope="scope">
          <el-button 
            type="primary"
            size="small"
            plain
            @click="pwdChange(scope.row, scope.$index, true)"
          >
            {{ scope.row.isSet ? "保存" : "编辑" }}
          </el-button>
          <el-button
            v-if="scope.row.isSet"
            type="info" 
            size="small"
            plain
            @click="pwdChange(scope.row, scope.$index, false)"
          >
            取消
          </el-button>
        </template>
      </el-table-column>
    </el-table>
  </div>
  
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  <script src="https://lib.baomitu.com/Sortable/1.14.0/Sortable.min.js"></script>
  <script>
    var app = new Vue({
      el: '#app',
      data() {
        return {
          selectRow: null,
          columns: [
            { field: "title", title: "标题", width: 120 },
            { field: "type", title: "图文", width: 150 },
            { field: "cover", title: "封面", width: 120 },
            { field: "date", title: "时间", width: 220 },
            { field: "digest", title: "摘要" },
          ],
          dataList: [
            {
              id: "1",
              title: "标题1",
              type: "图文",
              cover: "封面1",
              date: "2019-12-12 12:12:12",
              digest: "这是一段摘要内容1",
            },
            {
              id: "2",
              title: "标题2",
              type: "视频",
              cover: "封面2",
              date: "2019-12-12 12:12:12",
              digest: "这是一段摘要内容2",
            },
            {
              id: "3",
              title: "标题3",
              type: "图文3",
              cover: "封面3",
              date: "2019-12-12 12:12:12",
              digest: "这是一段摘要内容3",
            },
          ],
        };
      },
      mounted() {
        this.rowDrop();
      },
      methods: {
        //修改
        pwdChange(row, index, isEdit) {
          //点击修改 判断是否已经保存所有操作
          let ifset = this.dataList.some(item => {
            if(item.isSet && item.id != row.id) {
              return this.$message.warning("请先保存当前编辑项");
            }
          })
          if(ifset) return;

          //是否是取消操作
          if (!isEdit) {
            if (!this.selectRow.id) this.dataList.splice(index, 1);
            this.selectRow = null;
            return (row.isSet = !row.isSet);
          }
          
          //提交数据
          if (row.isSet) {
            let data = JSON.parse(JSON.stringify(this.selectRow));
            row = data;
            row.isSet = false;

            this.$message({
              type: "success",
              message: "保存成功!",
            });
            this.selectRow = null;
          } else {
            this.selectRow = JSON.parse(JSON.stringify(row));
            row.isSet = true;
          }
          this.$set(this.dataList,index,row)
        },
        tableRowClassName({ row }) {
          if (row.disabled) {
            return "disabled";
          }
          return "";
        },
        //行拖拽
        rowDrop() {
          const tbody = document.querySelector(".el-table__body-wrapper tbody");
          const _this = this;
          Sortable.create(tbody, {
            handle: ".move", //指定拖拽目标,点击此目标才可拖拽元素(此例中设置操作按钮拖拽)
            filter: ".disabled", //指定不可拖动的类名(el-table中可通过row-class-name设置行的class)
            dragClass: "dragClass", //设置拖拽样式类名
            ghostClass: "ghostClass", //设置拖拽停靠样式类名
            chosenClass: "chosenClass", //设置选中样式类名
            onEnd({ newIndex, oldIndex }) {
              const currRow = _this.dataList.splice(oldIndex, 1)[0];
              _this.dataList.splice(newIndex, 0, currRow);
            },
          });
        },
      },
    })
  </script>
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值