vue實現(xiàn)前端拖拽div位置交換的方法詳解
一、場景描述
類似備忘錄,點擊添加按鈕,多一條條目。然后手動拖拽條目可以更換條目之前的位置。
二、問題拆解
這里可以分成兩個問題,第一個是添加,第二個是拖拽。
添加的實現(xiàn):vue技術像一個前端頁面的數(shù)據(jù)管理器,它里面的 “v-for”列表渲染指令支持當列表數(shù)據(jù)增加的時候實現(xiàn)重新渲染增加一個條目。
拖拽的實現(xiàn):拖拽事件,開始的時候需要記錄所拖拽的目標,拖拽經過的實現(xiàn)交換。
三、知識背景
3.1 vue拖拽事件
在這里,我們使用的是開始拖拽事件和在有效區(qū)域移動事件,為的是得到所拖拽的標簽元素以及被拖動標簽元素所要到達的原有標簽元素的位置。
下面舉例一下拖拽事件怎么用。
首先需要開始標簽拖拽功能:draggable=“true” ,再添加拖拽事件。
<div class="task" draggable="true" @dragstart.self = "ondragstart($event)" @dragover.self = "ondragover($event)"> </div>
3.2 js獲得同級元素節(jié)點
ele.previousSibling ele.previousElementSibling 獲取同級的上下級,(前一個標簽元素和后一個標簽元素) ele.nextSibling ele.nextElementSibling
<input id="a5" type="button" onclick="console.log('previousSibling是'+this.previousSibling);" value="e" /> <!-- 這是個text對象,因為在這個標簽元素前面是一個換行符 --> <input id="a6" type="button" onclick="console.log(this.previousSibling);" value="e" /> <input id="a7" type="button" onclick="console.log('previousElementSibling是'+this.previousElementSibling);" value="e" /> <!-- 這是個標簽元素,因為在這個js代碼所取的是一個前一個標簽對象 --> <input id="a8" type="button" onclick="console.log(this.previousElementSibling);" value="e" />
四、場景實現(xiàn)
添加的實現(xiàn):就是用vue中的v-for指令。點擊按鈕之后,在列表中加一個列表元素,就會重新渲染。
拖拽的實現(xiàn):這里有兩種可能性,一個是如果是往前拖拽,則所要拖拽元素放在目標元素之前;如果是往后拖拽,則所要拖拽元素放在目標元素之后。
因此需要判斷目標元素是否是前面的元素。
isPreviousElements(sourse, target){ //這里是判斷前面是否還有元素,sourse是不是第一個元素 if(!sourse.previousElementSibling){ return false; } //這里是判斷 if(target.isEqualNode(sourse.previousElementSibling)){ return true; } return this.isPreviousElements(sourse.previousElementSibling, target) },
然后把標簽元素放入到目標元素之前或之后。
完整代碼
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>todayTask</title> <script src="../js/vue.js"></script> <style> .task{ width: 300px; height: 50px; list-style-type:decimal; list-style-position:inside; cursor: grab; position: absolute; transition: top; transition-duration: 0.6s; } .taskList{ position: relative; display: flex; flex-direction: column; } .addTask{ display: block; } </style> </head> <body> <div class="container"> <button class="addTask" @click="addTask">添加任務</button> <div class="taskList"> <div class="task" draggable="true" @dragstart.self = "ondragstart($event)" @dragover.self = "ondragover($event)" v-for="task in tasks" :key="task.id"> <span> {{task.id}} <input type="text" v-model="task.task"> </span> </div> </div> </div> </body> <script> document.body.addEventListener("dragover",function(ev){ ev.preventDefault(); }) new Vue({ el:".container", data:{ tasks:[ {id:1,task:"",isDone:false} ], dragDiv:"", isMoving:false }, methods:{ addTask(){ this.tasks.push({id:this.tasks.length+1,task:"",isDone:false}) var taskList = document.getElementsByClassName("taskList")[0]; taskList.style.height = this.tasks.length*50+"px" }, sortDiv(divs){ for(var i=0;i<divs.length;i++){ divs[i].style.top = i*50 + "px"; } }, isPreviousElements(sourse, target){ //返回上一節(jié)點 if(!sourse.previousElementSibling){ return false; } if(target.isEqualNode(sourse.previousElementSibling)){ return true; } return this.isPreviousElements(sourse.previousElementSibling, target) }, ondragstart(ev){ this.dragDiv = ev.target; console.log("dragstart"); }, ondragover(ev){ overDrag = ev.target; console.log(overDrag.isEqualNode(this.dragDiv)); console.log(this.isMoving); if(this.isMoving || overDrag.isEqualNode(this.dragDiv)){ return; } //判斷是否是前一個標簽元素 if(this.isPreviousElements(overDrag,this.dragDiv)){ overDrag.parentNode.insertBefore(this.dragDiv,overDrag.nextElementSibling); }else{ overDrag.parentNode.insertBefore(this.dragDiv,overDrag); } this.isMoving = true; const self = this; var st = setTimeout(function(){ self.isMoving = false; clearTimeout(st); },600); this.sortDiv(document.querySelectorAll(".task")); } }, created(){ //設置ul的盒子高度 var taskList = document.getElementsByClassName("taskList")[0]; taskList.style.height = this.tasks.length*50+"px"; //設置每一個item的上邊緣top this.sortDiv(document.querySelectorAll(".task")); }, updated(){ this.sortDiv(document.querySelectorAll(".task")); } }) </script> </html>
總結
到此這篇關于vue實現(xiàn)前端拖拽div位置交換的文章就介紹到這了,更多相關vue前端拖拽div位置交換內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
vue3中watch和watchEffect實戰(zhàn)梳理
這篇文章主要介紹了vue3中watch和watchEffect實戰(zhàn)梳理,watch和watchEffect都是vue3中的監(jiān)聽器,但是在寫法和使用上是有區(qū)別的。下文介紹他們之間的方法及區(qū)別,需要的朋友可以參考一下2022-07-07axios的interceptors多次執(zhí)行問題解決
這篇文章主要為大家介紹了axios中interceptors多次執(zhí)行問題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-06-06前端Vue.js實現(xiàn)json數(shù)據(jù)導出到doc
這篇文章主要介紹了前端Vue.js實現(xiàn)json數(shù)據(jù)導出到doc,文章圍繞主題展開詳細的內容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-09-09