原生js實現框選表格內容並批量更改(vue)

原生js實現框選表格內容並批量更改(vue)

前言

平常開發中,有這樣的需求,須要在表格中進行框選,並對框選中的內容進行批量更改。源碼於文章結尾javascript

demo

demo

下面連接供在線調試:html

https://codesandbox.io/s/tabl...vue

講解

主要思路經過監聽鼠標事件,進行框選框繪製。獲取框選 的dom,並計算其是否在框選區域,來進行批量更改。其中主要的方式 getClientRectsjava

業務代碼:

一、初始化表格數據結構node

由於表格爲星期/時間,相對結構會有點子複雜,問題不大,giao。git

setTableConfig() {
    let timeThArr = Array.from(new Array(24).keys());
    let timeTdArr = Array.from(new Array(48).keys());
    timeTdArr = timeTdArr.map((item) => {
      let obj = {
        id: item,
      };
      return obj;
    });
    this.timeThArr = timeThArr;
    this.timeTdArr = timeTdArr;

    let tableList = this.tableData;
    tableList.map((item, index) => {
      this.timeThArr.map((temp, key) => {
        item.push({
          key: key + index * 24,
        })
      })
    })
    this.tableData = tableList;
  },

二、點擊單格選中github

除了框選也能夠單擊選中web

handleClickTimeData(obj, index) {
    let tableList = _.clone(this.tableData);
    _.map(tableList[index], (item) => {
      if (item.key == obj.key) {
        item.checked = !item.checked;
      }
    });
    this.tableData = tableList;
},

三、重置數據結構

取消全部框選dom

reset() {
    let tableList = _.clone(this.tableData);
    _.map(tableList, (item) => {
      _.map(item, temp => {
        temp.checked = false;
      })
    });
    this.tableData = tableList;
},
框選代碼

一、表格綁定mousedown、mousemove、mouseup事件

handleMouseDown(e) {
    this.is_show_mask = true;
    this.start_x = e.clientX;
    this.start_y = e.clientY;
    this.end_x = e.clientX;
    this.end_y = e.clientY;
    document.body.addEventListener("mousemove", this.handleMouseMove);
    document.body.addEventListener("mouseup", this.handleMouseUp);
},
handleMouseMove(e) {
    this.end_x = e.clientX;
    this.end_y = e.clientY;
},
handleMouseUp() {
    document.body.removeEventListener("mousemove", this.handleMouseMove);
    document.body.removeEventListener("mouseup", this.handleMouseUp);
    this.is_show_mask = false;
    this.handleDomSelect();
    this.resetXY();
},

二、計算dom是否在包含在框選區域內部

collide(rect1, rect2) {
    const maxX = Math.max(rect1.x + rect1.width, rect2.x + rect2.width);
    const maxY = Math.max(rect1.y + rect1.height, rect2.y + rect2.height);
    const minX = Math.min(rect1.x, rect2.x);
    const minY = Math.min(rect1.y, rect2.y);
    if (
      maxX - minX <= rect1.width + rect2.width &&
      maxY - minY <= rect1.height + rect2.height
    ) {
      return true;
    } else {
      return false;
    }
},

三、鼠標鬆開後進行一系列操做

(1)首先獲取框選的dom,主要的方法爲getClientRects
(2)而後計算獲取的元素是否在框選範圍內
(3)對範圍內的dom進行後續操做

handleDomSelect() {
    const dom_mask = window.document.querySelector(".mask");
    const rect_select = dom_mask.getClientRects()[0];
    
    let selectKeys = [];
    document.querySelectorAll(".week-data-td").forEach((node, index) => {
      const rects = node.getClientRects()[0];
      if (this.collide(rects, rect_select) === true) {
        selectKeys.push(index);
      }
    });
    if (selectKeys.length < 2) return;
    let tableList = _.clone(this.tableData);
    tableList = _.map(tableList, (item, key) => {
      return _.map(item, (temp) => {
        if (selectKeys.indexOf(temp.key) > -1) {
          temp.checked = true;
        }
        return temp;
      });
    });
    this.tableData = tableList;
},

框選這部分代碼,具體參考大佬代碼

http://www.360doc.com/content...

源碼

https://github.com/ttypZhoupe...

末了

若是這篇文章對大佬有幫助,請不要吝嗇你的贊。來個一鍵三連就更好了,感謝大佬參閱。

相關文章
相關標籤/搜索