vue 通過 Ctrl 、Shift 鍵 + 點擊鼠標實現 div 多選操作


vue 通過 Ctrl 、Shift 鍵 + 點擊鼠標實現 div 多選操作

前言

我在做東西的時候有這樣一個需求,就是有一個div的列表,想通過按住Ctrl鍵后點擊div實現多選的功能,在一個是按住 Shift鍵都點擊前后兩個div選中區域的效果。

就是選擇下面圖片,每個圖片包含在一個div下面。
在這里插入圖片描述

邏輯

其實大體的邏輯就是:

  1. 進入頁面,開啟鍵盤監聽事件,監聽 Ctrl 鍵和 Shift 鍵的按下和抬起事件,因為需要在按住這兩個鍵的時候才可以實現多選功能。
  2. 在div上添加一個點擊事件,將div設置成一個選中的樣式,當然,在點擊事件里面得判斷一下,判斷鍵盤是不是被按下了,沒有按下的話,不做任何處理。

就是這么簡單的問題。

接下來就是相關主要代碼的編寫問題,因為每個人的項目和需求是不一樣的,所以我就簡單分享一下自己的主要代碼邏輯。

代碼

首先在vue項目里面定義幾個變量哈。

data() {
     return {
     	tableData: [],   // 假設這個是上邊小div的列表,后台數據請求回來的嗎,假設已經有數據了哈,里面有唯一標識符id
     	isshift: false,  // 快捷鍵 shift 是否被按下
        isctrl: false,   // 快捷鍵 ctrl 是否被按下
        selectedState: [],  // 上方div圖切是否被多選中,如果多選了就把他的id放到這個列表里面,當然可以不用,直接在相應的列表對象加一個參數isSelected也行,具體看項目和個人編碼習慣哈。
        shiftNum: '', // shift 按下后選擇的第一個div下標,因為shift的時候要點兩個div都中間包裹的都要切換為被選中狀態
	}
}

其次有一個鍵盤監聽事件

	  // 監聽鍵盤 
      keyDown() {
        // 鍵盤按下事件
        document.onkeydown = (e) => {
          // 取消默認事件
          e.preventDefault();   
          //事件對象兼容
          let e1 = e || event || window.event || arguments.callee.caller.arguments[0]
          //鍵盤按鍵判斷:左箭頭-37;上箭頭-38;右箭頭-39;下箭頭-40  回車:13   ctrl:17   shift:16
          switch (e1.keyCode) {
            case 16:
              this.isshift = true;  // 如果shift按下就讓他按下的標識符變為true
              break;
            case 17:
              this.isctrl = true;  // 如果ctrl按下就讓他按下的標識符變為true
              break;
          }
        }
        // 鍵盤抬起事件
        document.onkeyup = (e) => {
          // 取消默認事件
          e.preventDefault();
          //事件對象兼容
          let e1 = e || event || window.event || arguments.callee.caller.arguments[0]
          switch (e.keyCode) {
            case 16:  
              this.shiftNum = ''
              this.isshift = false; // 如果shift抬起下就讓他按下的標識符變為false
              break;
            case 17:
              this.isctrl = false;  // 如果ctrl抬起下就讓他按下的標識符變為false
              break;
          }
        }
      },

這樣ctrl和shift鍵的監聽事件就完成了,上面的方法在頁面初始化完成的時候調用一下子哈,別忘了。

activated() {
	this.keyDown()
}

接下來就是點擊小div的邏輯了。

給小div一個點擊事件,我還寫嗎?都知道哈,寫一下子吧, 不寫樣式了,當然循環的時候不要用index,我這瞎寫的,不要計較哈,分享一下,主要是說多選功能。

<div v-for="(item, index)  in tableData" :key="index">
	<div @click="selectImage(item, index)">
	</div>
</div>

好了,大體就是這個意思,然后點擊的時候把這個數據對象傳進去,里面包含着一個表示這個div的唯一標識符id。

然后就是最重要的多選的邏輯處理。

selectImage(item, index) {
        if (this.isctrl) {  // 如果按下的是ctrl
          let str = item.id // 這行代碼沒必要,但是案例是根據我項目改的,就懶得刪了
          let i = this.selectedState.indexOf(str)  // 判斷選中列表中是否包含這個點擊的div
          if (i < 0) {
            this.selectedState.push(str)   // 如果不包含就加進去
          } else {
            this.selectedState.splice(i, 1);  // 如果包含就刪,表示按下ctrl鍵點一下選中,在點一下取消選中
          }
        } else if (this.isshift) {   // 如果按下的是shift
          if (this.shiftNum === '') {  // 如果還沒點下第一個div
            this.shiftNum = index  // 讓第一個div的下標賦值給shiftNum
            let str = item.id
            let i = this.selectedState.indexOf(str)
            if (i < 0) {
              this.selectedState.push(str)
            } else {
              this.selectedState.splice(i, 1);
            }
          } else {  // 如果點擊第一個了
            if (this.shiftNum > index) {  // 選中第一個的索引大於當前點擊的索引
              for (let j = index; j <= this.shiftNum; j++) {  // 把中間的都選中
                let str = this.tableData[j].id
                let i = this.selectedState.indexOf(str)
                if (i < 0) {
                  this.selectedState.push(str)
                }
              }
            } else {
              for (let j = this.shiftNum; j <= index; j++) {
                let str = this.tableData[j].id
                let i = this.selectedState.indexOf(str)
                if (i < 0) {
                  this.selectedState.push(str)
                }
              }
            }
          }
        }
      },

ok,這樣就可以了。

選中樣式的話我就不寫了,根據自己的喜好自己寫就可以了,可以根據div的id是否包含在selectedState數組里面進行判斷是否被選中。

太厲害了我!哈哈哈哈!!!

下面是我做的項目的大體樣式,主要就是上邊的邏輯。

在這里插入圖片描述


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM