Vue使用自定義指令實(shí)現(xiàn)拖拽行為實(shí)例分析
本文實(shí)例講述了Vue使用自定義指令實(shí)現(xiàn)拖拽行為。分享給大家供大家參考,具體如下:
需求
通過自定義指令的方式實(shí)現(xiàn)拖拽效果,預(yù)期的使用方式為:
<div style="background: #f00; width: 200px; height: 200px;" v-drag> XXXX </div>
更重要的一個(gè)需求點(diǎn):
- 拖拽元素內(nèi)部的子元素可以自行阻止拖拽行為
比如:
<div style="background: #f00; width: 200px; height: 200px;" v-drag> <el-button @mousedown.native.stop>test</el-button> </div>
曾經(jīng)使用過vue-resizable
,由于該組件是通過事件捕獲的方式實(shí)現(xiàn)的,拖拽元素的子元素也會(huì)觸發(fā)拖拽行為,不符合開發(fā)需求,所以自行實(shí)現(xiàn)了拖拽指令,相關(guān)源碼如下。
無任何依賴,復(fù)制即可使用
源碼
/** * @file 自定義拖拽命令 */ import Vue from 'vue'; const Drag = { install(Vue: any) { // 如需禁止拖拽元素內(nèi)部某些元素觸發(fā)拖拽,在內(nèi)部不可觸發(fā)拖拽元素上添加@mousedown.native.stop即可 Vue.directive('drag', { bind(el: any) { el.style.position = 'absolute'; el.style.zIndex = el.style.zIndex || '3000'; }, inserted(el: any) { // 設(shè)置元素初始位置 const boundingClientRect = el.getBoundingClientRect(); el.style.left = boundingClientRect.x + 'px'; el.style.top = boundingClientRect.y + 'px'; // 將拖拽元素置于body子元素,防止被relative的父元素遮擋 document.body.appendChild(el); let originX: number; let originY: number; const mouseDownHandler = (evt: MouseEvent) => { originX = evt.clientX - el.offsetLeft; originY = evt.clientY - el.offsetTop; el.style.cursor = 'pointer'; }; const mouseMoveHandler = (evt: MouseEvent) => { if (evt.buttons === 1 && originX && originY) { el.style.left = evt.clientX - originX + 'px'; el.style.top = evt.clientY - originY + 'px'; } }; const mouseUpHandler = () => { el.style.cursor = 'default'; }; el.addEventListener('mousedown', mouseDownHandler); el.addEventListener('mousemove', mouseMoveHandler); el.addEventListener('mouseup', mouseUpHandler); el.__mouseDownHandler__ = mouseDownHandler; el.__mouseMoveHandler__ = mouseMoveHandler; el.__mouseUpHandler__ = mouseUpHandler; }, unbind(el: any) { el.removeEventListener('mousedown', el.__mouseDownHandler__); el.removeEventListener('mousemove', el.__mouseMoveHandler__); el.removeEventListener('mouseup', el.__mouseUpHandler__); // 當(dāng)父組件銷毀觸發(fā)unbind的時(shí)候需要手動(dòng)刪除這個(gè)節(jié)點(diǎn),不然會(huì)一直存留在body中 el.parentNode.removeChild(el); } }); } }; Vue.use(Drag); export default Drag;
希望本文所述對(duì)大家vue.js程序設(shè)計(jì)有所幫助。
相關(guān)文章
vue項(xiàng)目中created()被調(diào)用多次的踩坑實(shí)戰(zhàn)
在vue項(xiàng)目中我在created中調(diào)用了兩次get數(shù)據(jù)請(qǐng)求,所以下面這篇文章主要給大家介紹了關(guān)于vue項(xiàng)目中created()被調(diào)用多次的踩坑實(shí)戰(zhàn),需要的朋友可以參考下2023-03-03MAC+PyCharm+Flask+Vue.js搭建系統(tǒng)
最近新做了個(gè)項(xiàng)目,使用的是MAC+PyCharm+Flask+Vue.js搭建系統(tǒng),本文就來分享一下搭建步驟,感興趣的可以了解一下2021-05-05解決element ui select下拉框不回顯數(shù)據(jù)問題的解決
這篇文章主要介紹了解決element ui select下拉框不回顯數(shù)據(jù)問題的解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-02-02在vue3中使用el-tree-select實(shí)現(xiàn)樹形下拉選擇器效果
el-tree-select是一個(gè)含有下拉菜單的樹形選擇器,結(jié)合了?el-tree?和?el-select?兩個(gè)組件的功能,這篇文章主要介紹了在vue3中使用el-tree-select做一個(gè)樹形下拉選擇器,需要的朋友可以參考下2024-03-03Vue from-validate 表單驗(yàn)證的示例代碼
本篇文章主要介紹了Vue from-validate 表單驗(yàn)證的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-09-09