原生Javascript實現表格行上下拖拽

拖放事件:
拖動元素時,依次觸發的事件:

  • dragstart 按下鼠標並移動時觸發
  • drag 拖動期間持續觸發
  • dragend 鬆開鼠標觸發

拖動到有效的放置目標上時,依次觸發:

  • dragenter 元素被拖到放置目標上
  • dragover 被拖元素在放置目標內移動,持續觸發
  • dragleave或drop dragleave,元素被拖到放置目標外觸發;drop元素被拖到有效的放置目標上(默認無效),並鬆開鼠標觸發

實現代碼:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>table</title>
    <style>
    	tr,th {
    		padding: 30px;
    	}
    </style>
</head>
<body>
	<table id="myTable" border="1" >
		<tbody>
			<tr>
				<th>序列</th>
				<th>名稱</th>
				<th>單價</th>
				<th>數量</th>
			</tr>
			<tr draggable="true">
				<td>1</td>
				<td>冰箱</td>
				<td>13</td>
				<td>14</td>
			</tr>
			<tr draggable="true">
				<td>2</td>
				<td>彩電</td>
				<td>113</td>
				<td>114</td>
			</tr>
			<tr draggable="true">
				<td>3</td>
				<td>空調</td>
				<td>12</td>
				<td>12</td>
			</tr>
			<tr draggable="true">
				<td>4</td>
				<td>洗衣機</td>
				<td>12</td>
				<td>12</td>
			</tr>
		</tbody>
	</table>
	<script>
	function drag_row_table() {
		var EventUtil = {  //跨瀏覽器的事件處理程序,視情況分別選擇以下事件處理程序
			addHandler: function(element, type, handler) {
				if(element.addEventListener) {  //DOM2級
					element.addEventListener(type, handler, false);
				}
				else if (element.attachEvent) {  //IE方法
					element.attachEvent('on' + type.handler);
				}
				else {  //DOM1級
					element["on" + type] = handler;
				}
			},
			preventDefault: function(event) {  //取消事件默認方法
				if(event.preventDefault) {  
					event.preventDefault();
				}
				else {
					event.returnValue = false;  //默認爲true,設爲falsew爲取消默認行爲。
				}
			}
		}

		var myTable = document.querySelector('#myTable');
		var tbody = document.querySelector("tbody");
		var trs = myTable.querySelectorAll("tr");

		for(var i=1; i < trs.length; i++) {  //爲每一行註冊監聽事件

			EventUtil.addHandler(trs[i], "dragover", function(event) { //默認元素不可放置,這裏取消默認,將放置目標修改爲可放置的
				EventUtil.preventDefault(event);  
			})

			EventUtil.addHandler(trs[i], "dragstart", function(event) {  //監聽點擊的拖動的元素
				event.dataTransfer.setData("drag_index", event.currentTarget.rowIndex); //將被拖元素的信息,傳給放置位置
			})

			EventUtil.addHandler(trs[i], "drop", function(event) {  //監聽鼠標移動到可放置的放置目標上,鬆開鼠標的事件
				EventUtil.preventDefault(event);  //取消在Firefox 3.5+中,放置事件的默認行爲是打開被放置目標上的URL
				let drag_index = parseInt(event.dataTransfer.getData("drag_index"));  //獲取傳過來的被拖元素的信息
				let drop_index = this.rowIndex;  //this爲當前觸發drop的元素,即放置目標的行下標
				tbody.insertBefore(trs[drag_index], this.nextSibling);   //將被拖元素放到放置目標的兄弟節點上
				trs = myTable.querySelectorAll("tr");  //更新變換的tr行信息
			})
		}
	}

	drag_row_table();
	</script>
</body>
</html>

效果:
在這裏插入圖片描述
這裏遇到的坑是,querySelectorAll()方法的底層實現是類似於一組元素的快照,而不是動態查詢的(即更新文檔結構時,對應的變量也自動更新),爲的是避免使用NodeList對象引起的性能問題。因此我們得手動更新querySelectorAll()方法的變量。
符合動態查詢的方法有getElementsByTagName()

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章