Element UI table点击选中行/取消选中 快捷多选 以及快捷连续多选,高亮选中行

[转载自]:https://juejin.cn/post/6844903910734299150

ElementUI table自带的有一个highlight-current-row的属性,但是只能单选。所以要实现点击行选中以及多选得自己实现.

目标:单击选中/取消, 按ctrl键点击实现多选 ,按shift/alt键实现连续多选。

1. 监听row-click事件,实现选中
 <el-table ref="multipleTable" 
            :data="tableData"
            style="width: 100%"
            @selection-change="handleSelectionChange"
            @row-click="rowClick" 
            :row-style="rowStyle"
            :row-class-name="rowClassName">
            .....
            .....
</el-table>
rowClick(row, column, event) {

   let refsElTable = this.$refs.multipleTable; // 获取表格对象
   refsElTable.toggleRowSelection(row); // 调用选中行方法
}
2. 实现选中取消,以及单个选中

上面已经实现点击选中,但是会点击一行选中一行,所以要使用clearSelection先清空之前选择的行,然后进行选择,取消选择首先要确定当前点击的行是否被已被选中,所以先监听selection-change事件保存已选中行(或者使用$refs获取内部保存的已选择行),以及使用row-style给每一行添加唯一标识。

rowClick(row, column, event) {
       let refsElTable = this.$refs.multipleTable; // 获取表格对象
       let findRow = this.selectionRow.find(c => c.rowIndex == row.rowIndex);
       if (findRow ) {
           refsElTable.toggleRowSelection(row, false);
            return;
       }
       refsElTable.clearSelection();
       refsElTable.toggleRowSelection(row); // 调用选中行方法
},

rowStyle({row,rowIndex}) {
         Object.defineProperty(row, 'rowIndex', { //给每一行添加不可枚举属性rowIndex来标识当前行
         value: rowIndex, 
         writable: true,
         enumerable: false
       })
 },

handleSelectionChange(rows) {
      this.selectionRow = rows //保存已选择行
  },
3. 按住ctrl实现多选

首先要监听keydown事件,以及keyup事件

methods: {
    rowClick(row, column, event) {
       let refsElTable = this.$refs.multipleTable; // 获取表格对象
         if (this.CtrlDown) {
              refsElTable.toggleRowSelection(row); // ctrl多选 如果点击两次同样会取消选中
              return;
       }
       let findRow = this.selectionRow.find(c => c.rowIndex == row.rowIndex);
       if (findRow ) {
           refsElTable.toggleRowSelection(row, false);
            return;
       }

       refsElTable.clearSelection();
       refsElTable.toggleRowSelection(row); // 调用选中行方法
    },


    keyDown(event) {
                let key = event.keyCode;
                if (key == 17) this.CtrlDown = true;
            },


    keyUp(event) {
                let key = event.keyCode;
                if (key == 17) this.CtrlDown = false;
        },
},
mounted() {
    addEventListener("keydown", this.keyDown, false);
    addEventListener("keyup", this.keyUp, false);
 },
beforeDestroy() { //解绑
    removeEventListener("keydown", this.keyDown);
    removeEventListener("keyup", this.keyUp);
}
4. shift/alt键实现连续多选

这一步要通过rowIndex判断已选择的行中最上面和最下面的是哪行,再对比按住shift/alt点击的当前行得到新的最上面和最下面的行,把这两行中间的行进行循环选中。

computed: { //实时得到最上行和最下行
    bottomSelectionRow() {
          if (this.selectionRow.length == 0) return null;
            return this.selectionRow.reduce((start, end) => {
                  return start.rowIndex > end.rowIndex ? start : end;
              });
        },
    topSelectionRow() {
           if (this.selectionRow.length == 0) return null;
              return this.selectionRow.reduce((start, end) => {
                  return start.rowIndex < end.rowIndex ? start : end;
              });
          }
   },

methods: {
   rowClick(row, column, event) {
       let refsElTable = this.$refs.multipleTable; // 获取表格对象
         if (this.CtrlDown) {
              refsElTable.toggleRowSelection(row); // ctrl多选 如果点击两次同样会取消选中
              return;
         }
       
       if ( this.shiftOrAltDown && this.selectionRow.length > 0) { 
                    let topAndBottom = getTopAndBottom(  row, this.bottomSelectionRow, this.topSelectionRow );
                    refsElTable.clearSelection(); //先清空 不然会导致在这两行中间之外的行状态不变
                    for (let index = topAndBottom.top; index <= topAndBottom.bottom; index++) { //选中两行之间的所有行
                        refsElTable.toggleRowSelection(this.tableData[index], true);
                    }
         } else {
              let findRow = this.selectionRow.find(c => c.rowIndex == row.rowIndex); //找出当前选中行
               //如果只有一行且点击的也是这一行则取消选择 否则清空再选中当前点击行
               if (findRow&& this.selectionRow.length === 1 ) { 
                  refsElTable.toggleRowSelection(row, false);
                  return;
                 }
                 refsElTable.clearSelection();
                 refsElTable.toggleRowSelection(row); 
        }
    },

    rowStyle({row,rowIndex}) {
         Object.defineProperty(row, 'rowIndex', { //给每一行添加不可枚举属性rowIndex来标识当前行
         value: rowIndex, 
         writable: true,
         enumerable: false
       })
   },

    keyDown(event) {
                let key = event.keyCode;
                if (key == 17) this.CtrlDown = true;
                if (key == 16 || key == 18) this.shiftOrAltDown = true;
            },


    keyUp(event) {
                let key = event.keyCode;
                if (key == 17) this.CtrlDown = false;
                if (key == 16 || key == 18) this.shiftOrAltDown = false;
        },
},

mounted() {
    addEventListener("keydown", this.keyDown, false);
    addEventListener("keyup", this.keyUp, false);
 },

beforeDestroy() { //解绑
    removeEventListener("keydown", this.keyDown);
    removeEventListener("keyup", this.keyUp);
}

/**获取最新最上最下行 */
function getTopAndBottom(row, bottom, top) {
        let n = row.rowIndex,
            mx = bottom.rowIndex,
            mi = top.rowIndex;
        if (n > mx) {
            return {
                top: mi,
                bottom: n
            };
        } else if (n < mx && n > mi) {
            return {
                top: mi,
                bottom: n
            };
        } else if (n < mi) {
            return {
                top: n,
                bottom: mx
            };
        } else if (n == mi || n == mx) {
            return {
                top: mi,
                bottom: mx
            };
        }
    };
5. 实现选中高亮

跟element-ui本身的单选高亮实现方式一样,都是给选中行加上current-row这个class类,所以要使用row-class-name这个属性(其实给每一行添加rowIndex也可以用这个属性),判断方式也是通过判断rowIndex对比

rowClassName({ row,  rowIndex }) {
          let rowName = "",
          findRow = this.selectionRow.find(c => c.rowIndex === row.rowIndex);
         if (findRow) {
           rowName = "current-row "; // elementUI 默认高亮行的class类 不用再样式了^-^,也可通过css覆盖改变背景颜色
      }
    return rowName; //也可以再加上其他类名 如果有需求的话
 },
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343