element-ui 的表格裡面使用 el-popover 實現編輯彈層功能

凱小默發表於2020-12-19

功能點

1、表格是沒有分頁的

2、點選編輯能定位到對應的位置,進行編輯功能

3、表格滾動時候,編輯彈層需要關閉

效果

在這裡插入圖片描述

程式碼實現

<template>
<el-table ref="multipleTable" >
<el-table-column label="操作" width="90">
  <template slot-scope="scope">
    <el-button type="text" @click="handleClickEdit(scope.row, $event)">編輯</el-button>
  </template>
</el-table-column>
</el-table>


<!-- 編輯模板 -->
<el-popover ref="editPopover" placement="bottom-end" width="370"
    v-model="visibleEdit"  :reference="prevTarget" :key="popperFlag"
></el-popover>
</template>

<script>
// 節流-防抖
import { throttle } from 'throttle-debounce';

export default {
  data() {
    return {
      visibleEdit: false,
      prevTarget: null, // 編輯 Popover 的 Reference (參照),用於 popover.js 對齊兩個元素
      popperFlag: false, // 用於編輯 Popover 的重新整理
    };
  },
  watch: {
    value(n) {
      if(n) {
        this.$nextTick(() => {
          // 新增這個用於處理fixed定位導致的列表行錯位
          console.log('this.$refs.multipleTable--->', this.$refs.multipleTable);
          this.$refs.multipleTable.doLayout();
        });
        // 監聽滾動,用於編輯框的滾動移除
        this.removeEditPopoverListener(n);
      }
    }
  },
  methods: {
    // 監聽滾動,用於編輯框的滾動移除
    removeEditPopoverListener(flag) {
      let timer = setTimeout(() => {
        let scrollElement = this.$refs.multipleTable.$el.querySelector('.el-table__body-wrapper');
        console.log('監聽滾動,用於編輯框的滾動移除', flag, scrollElement);
        // 
        let scrollHandle = () => {
          console.log('執行--->', this.visibleEditOpinions);
          if (this.visibleEditOpinions) {
            this.clearEditPopperComponent();
          }
        }
        if (flag) {
          // 滾動節流
          scrollElement.addEventListener('scroll', throttle(500, scrollHandle));
        } else {
          scrollElement.removeEventListener('scroll', scrollHandle);
        }
        clearTimeout(timer);
      }, 0);
    },
    // 核取方塊選中的資料
    changeSelection(row) {
      this.selectData = row;
      console.log('核取方塊選中的資料', this.selectData);
      this.seqs = this.selectData.map((el) => { return el.seq; }).toString();
      console.log('seqs---->', this.seqs);
    },
    // 清空編輯元件
    clearEditPopperComponent() {
      this.prevTarget = null;
      this.popperFlag = !this.popperFlag;
      this.visibleEdit = false;
    },
    // 點選編輯
    handleClickEdit(row, e) {
      //阻止事件冒泡,相容ie
      if (event.stopPropagation) {
        event.stopPropagation();
      } else if (window.event) {
        window.event.cancelBubble = true;
      }
      let currentTarget = e.target; // 賦值當前點選的編輯
      this.editData = row; // 設定編輯資料
      // 判斷是否需要切換
      if (this.prevTarget === currentTarget) {
        // 同一個元素重複點選
        this.visibleEdit = !this.visibleEdit;
      } else {
        // 切換不同元素, 判斷之前是否有點選其他編輯 prevTarget
        if (this.prevTarget) {
          // 先清除之前的編輯框
          this.clearEditPopperComponent();
          // 然後生成新的編輯框
          this.$nextTick(() => {
            this.prevTarget = currentTarget;
            this.visibleEdit = true;
          });
        } else {
          // 首次
          console.log('首次--->this.prevTarget');
          this.prevTarget = currentTarget;
          this.visibleEdit = true;
        }
      }
    }
  }
};
</script>

注意點

1、fixed 定位導致的列表行錯位

2、監聽滾動函式名必須具名,不然滾動的時候會導致記憶體問題,瀏覽器直接崩潰,也不能移出對應的滾動事件

3、reference 這個屬性 element 文件只說了 slot 的使用,需要去看原始碼

在這裡插入圖片描述

為什麼要用reference這樣做的原因?

如果將 el-popoper 寫在表格的編輯裡,使用 slot 的話,表格資料一多就會有效能問題,頁面很卡資料載入很慢,並且每次點選其他的編輯,會導致元件更新多次,另外,滾動的時候需要關閉,不然會編輯框滾來滾去,滾動的時候就需要考慮節流的問題。這樣一來就基本在能接受的範圍內。

js 庫連線

popover.js

throttle-debounce

相關文章