Vue實現(xiàn)拖拽穿梭框功能四種方式實例詳解
一、使用原生js實現(xiàn)拖拽
<html lang="en"> <head> <meta charset="UTF-8" /> <title>Lazyload</title> <style> .drag { background-color: skyblue; position: absolute; line-height: 100px; text-align: center; width: 100px; height: 100px; } </style> </head> <body> <!-- left和top要寫在行內(nèi)樣式里面 --> <div class="drag" style="left: 0; top: 0">按住拖動</div> <script src="./jquery-3.6.0.min.js"></script> <script> // 獲取DOM元素 let dragDiv = document.getElementsByClassName('drag')[0] // 鼠標(biāo)按下事件 處理程序 let putDown = function (event) { dragDiv.style.cursor = 'pointer' let offsetX = parseInt(dragDiv.style.left) // 獲取當(dāng)前的x軸距離 let offsetY = parseInt(dragDiv.style.top) // 獲取當(dāng)前的y軸距離 let innerX = event.clientX - offsetX // 獲取鼠標(biāo)在方塊內(nèi)的x軸距 let innerY = event.clientY - offsetY // 獲取鼠標(biāo)在方塊內(nèi)的y軸距 // 按住鼠標(biāo)時為div添加一個border dragDiv.style.borderStyle = 'solid' dragDiv.style.borderColor = 'red' dragDiv.style.borderWidth = '3px' // 鼠標(biāo)移動的時候不停的修改div的left和top值 document.onmousemove = function (event) { dragDiv.style.left = event.clientX - innerX + 'px' dragDiv.style.top = event.clientY - innerY + 'px' // 邊界判斷 if (parseInt(dragDiv.style.left) <= 0) { dragDiv.style.left = '0px' } if (parseInt(dragDiv.style.top) <= 0) { dragDiv.style.top = '0px' } if ( parseInt(dragDiv.style.left) >= window.innerWidth - parseInt(dragDiv.style.width) ) { dragDiv.style.left = window.innerWidth - parseInt(dragDiv.style.width) + 'px' } if ( parseInt(dragDiv.style.top) >= window.innerHeight - parseInt(dragDiv.style.height) ) { dragDiv.style.top = window.innerHeight - parseInt(dragDiv.style.height) + 'px' } } // 鼠標(biāo)抬起時,清除綁定在文檔上的mousemove和mouseup事件 // 否則鼠標(biāo)抬起后還可以繼續(xù)拖拽方塊 document.onmouseup = function () { document.onmousemove = null document.onmouseup = null // 清除border dragDiv.style.borderStyle = '' dragDiv.style.borderColor = '' dragDiv.style.borderWidth = '' } } // 綁定鼠標(biāo)按下事件 dragDiv.addEventListener('mousedown', putDown, false) </script> </body> </html>
二、VUe使用js實現(xiàn)拖拽穿梭框
<template> <div> <h3 style="text-align: center">拖拽穿梭框</h3> <div id="home" @mousemove="mousemove($event)"> <div class="tree-select-content"> <span class="select-content" :id="'mouse' + index" v-for="(item, index) in leftData" :key="item.id" @mousedown="mousedown(index, 1)" @mouseup="mouseup(item, 1, index)" > <span class="select-text">{{ item.label }}</span> <span class="select-text-X" @click="handerClickX(item, index, 1)" >X</span > </span> </div> <div class="tree-select-content"> <span class="select-content" :id="'deleteMouse' + index" v-for="(item, index) in rightData" :key="item.id" @mousedown="mousedown(index, 2)" @mouseup="mouseup(item, 2, index)" > <span class="select-text">{{ item.label }}</span> <span class="select-text-X" @click="handerClickX(item, index, 2)" >X</span > </span> </div> </div> </div> </template> <script> export default { name: "home", data() { return { leftData: [ { label: "首頁", id: 1 }, { label: "咨詢", id: 2 }, { label: "生活", id: 3 }, { label: "財富", id: 4 }, { label: "我的", id: 5 }, ], rightData: [{ label: "世界", id: 6 }], isMoveTrue: false, isMove: false, moveId: "", }; }, mounted() {}, components: {}, methods: { mousedown(index, val) { this.isMoveTrue = true; if (val == 1) { this.moveId = "mouse" + index; } else { this.moveId = "deleteMouse" + index; } }, mousemove(event) { if (this.isMoveTrue) { this.isMove = true; document.getElementById(this.moveId).style.position = "absolute"; document.getElementById(this.moveId).style.top = event.clientY + "px"; document.getElementById(this.moveId).style.left = event.clientX + "px"; document.getElementById(this.moveId).style.transform = "translate(-50%,-50%)"; } }, mouseup(item, val, index) { if (!this.isMove) { this.isMoveTrue = false; this.moveId = ""; } if (this.isMoveTrue && val == 2) { this.$nextTick(() => { this.rightData.splice(index, 1); this.leftData.push(item); }); } else if (this.isMoveTrue && val) { this.leftData.splice(index, 1); this.rightData.push(item); } document.getElementById(this.moveId).style.display = "none"; this.isMoveTrue = false; this.isMove = false; this.moveId = ""; }, handerClickX(item, index, val) { if (val == 1) { this.leftData.splice(index, 1); this.rightData.push(item); } else { this.rightData.splice(index, 1); this.leftData.push(item); } }, }, }; </script> <style scoped> #home { display: flex; justify-content: space-around; } .tree-select-content { width: 40%; height: 300px; background: #f9faff; border: 1px solid #dee0ec; border-radius: 4px; display: flex; flex-wrap: wrap; align-content: baseline; } .select-content { width: max-content; height: 20px; padding: 1.6%; border: 1px solid #d6dbed; margin: 2% 1% 0; background: #ffffff; box-shadow: 0 0 8px 0 rgba(72, 119, 236, 0.1); border-radius: 4px; } .select-content:hover span { color: #4877ec; } .select-content:hover { cursor: pointer; background: #f8faff; border: 1px solid #3e75f4; } .select-text { font-size: 15px; color: #2e2f36; text-align: center; font-weight: 400; } .select-text-X { font-size: 15px; color: #4877ec; letter-spacing: 0; font-weight: 400; margin-left: 12px; cursor: pointer; } </style>
效果圖:
三、Vue 拖拽組件 vuedraggable
vuedraggable
是標(biāo)準(zhǔn)的組件式封裝,并且將可拖動元素放進(jìn)了 transition-group
上面,過渡動畫都比較好。
使用方式:
yarn add vuedraggable import vuedraggable from 'vuedraggable';
在使用的時候,可以通過 v-model 來雙向綁定本地 data,如果需要更新或者是觸發(fā)父組件監(jiān)聽的事件,可以在 updated() 中去 emit。
案例:
<template> <div> <div>{{ drag ? "拖拽中" : "拖拽停止" }}</div> <!--使用draggable組件--> <draggable v-model="myArray" chosenClass="chosen" forceFallback="true" group="people" animation="1000" @start="onStart" @end="onEnd" > <transition-group> <div class="item" v-for="element in myArray" :key="element.id"> {{ element.name }} </div> </transition-group> </draggable> <div class="color-list"> <div class="color-item" v-for="color in colors" v-dragging="{ item: color, list: colors, group: 'color' }" :key="color.text" > {{ color.text }} </div> </div> </div> </template> <style scoped> /*被拖拽對象的樣式*/ .item { padding: 6px; background-color: #fdfdfd; border: solid 1px #eee; margin-bottom: 10px; cursor: move; } /*選中樣式*/ .chosen { border: solid 1px #3089dc !important; } </style> <script> //導(dǎo)入draggable組件 import draggable from "vuedraggable"; export default { //注冊draggable組件 components: { draggable, }, data() { return { drag: false, //定義要被拖拽對象的數(shù)組 myArray: [ { people: "cn", id: 10, name: "www.itxst.com" }, { people: "cn", id: 20, name: "www.baidu.com" }, { people: "cn", id: 30, name: "www.taobao.com" }, { people: "us", id: 40, name: "www.yahoo.com" }, ], colors: [ { text: "Aquamarine", }, { text: "Hotpink", }, { text: "Gold", }, { text: "Crimson", }, { text: "Blueviolet", }, { text: "Lightblue", }, { text: "Cornflowerblue", }, { text: "Skyblue", }, { text: "Burlywood", }, ], }; }, methods: { //開始拖拽事件 onStart() { this.drag = true; }, //拖拽結(jié)束事件 onEnd() { this.drag = false; }, }, }; </script>
四、Awe-dnd指令封裝
vue-dragging 的 npm 包的名字是 awe-dnd ,并不是 vue-dragging,這個庫的特點是封裝了 v-dragging 全局指令,然后通過全局指令去數(shù)據(jù)綁定等。
相比及 vuedraggable 來說, awe-dnd 是沒有雙向綁定(這里沒有雙向綁定并不是很嚴(yán)謹(jǐn),準(zhǔn)確的來說沒有暴露雙向綁定的方式),因此提供了事件,在拖拽結(jié)束的時候用來更新列表(不需要手動更新列表,其實內(nèi)部是實現(xiàn)了雙向綁定的)或者是去觸發(fā)父組件監(jiān)聽的事件。
安裝依賴:
npm install awe-dnd --save yarn add awe-and
main.js
import VueDND from 'awe-dnd' Vue.use(VueDND)
案例:
<template> <div> <div class="color-list"> <div class="color-item" v-for="color in colors" v-dragging="{ item: color, list: colors, group: 'color' }" :key="color.text" > {{ color.text }} </div> </div> </div> </template> <style scoped> /*被拖拽對象的樣式*/ .item { padding: 6px; background-color: #fdfdfd; border: solid 1px #eee; margin-bottom: 10px; cursor: move; } /*選中樣式*/ .chosen { border: solid 1px #3089dc !important; } </style> <script> export default { data() { return { drag: false, colors: [ { text: "Aquamarine", }, { text: "Hotpink", }, { text: "Gold", }, { text: "Crimson", }, { text: "Blueviolet", }, { text: "Lightblue", }, { text: "Cornflowerblue", }, { text: "Skyblue", }, { text: "Burlywood", }, ], }; }, methods: {}, }; </script>
到此這篇關(guān)于Vue實現(xiàn)拖拽穿梭框功能四種方式的文章就介紹到這了,更多相關(guān)vue拖拽穿梭框內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vuex狀態(tài)機(jī)的快速了解與實例應(yīng)用
Vuex是專門為Vuejs應(yīng)用程序設(shè)計的狀態(tài)管理工具,這篇文章主要給大家介紹了關(guān)于Vuex狀態(tài)機(jī)快速了解與實例應(yīng)用的相關(guān)資料,需要的朋友可以參考下2021-06-06使用Bootstrap + Vue.js實現(xiàn)添加刪除數(shù)據(jù)示例
本篇文章主要介紹了使用Bootstrap + Vue.js實現(xiàn) 添加刪除數(shù)據(jù)示例,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-02-02vue+scss+element-ui實現(xiàn)表格表頭斜杠一分為三方式
這篇文章主要介紹了vue+scss+element-ui實現(xiàn)表格表頭斜杠一分為三方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08