前言
被推拽元素,与其父元素,须放弃子绝父相,或子绝父绝。
案例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0 , maximum-scale=1, minimum-scale=1, user-scalable=no" />
<title>Vue 自定义指令:拖拽 </title>
<link rel="shortcut icon" href="https://gw.alipayobjects.com/mdn/prod_resou/afts/img/A*CUIoT4xopNYAAAAAAAAAAABkARQnAQ" type="image/x-icon" />
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.13/vue.js"></script>
<style>
* {
margin: 0;
padding: 0;
overflow: hidden;
box-sizing: border-box;
}
#app {
width: 100vw;
height: 100vh;
overflow: hidden;
}
.box {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
width: 100px;
height: 100px;
border-radius: 10px;
color: #fff;
background-color: cadetblue;
font-size: 60px;
font-weight: bold;
}
</style>
</head>
<body>
<div id="app">
<div class="box" v-drag>1</div>
<div class="box" v-drag>2</div>
<div class="box" v-drag>3</div>
<div class="box" v-drag>4</div>
<div class="box" v-drag>5</div>
<div class="box" v-drag>6</div>
<div class="box" v-drag>7</div>
<div class="box" v-drag>8</div>
<div class="box" v-drag>9</div>
</div>
<script>
// 设置为 false 以阻止 Vue 在启动时生成生产提醒
Vue.config.productionTip = false
// new 一个 Vue 实例,并挂载到 #app 上
new Vue({
el: '#app',
data() {return {}
},
directives: {
// 对象写法,利用 inserted 钩子确保元素曾经被插入 DOM 时才执行
drag: {inserted(el) {el.onmousedown = (event) => {
const parentEl = el.parentElement
// 避免选中拖拽导致登程浏览器的搜寻事件
event.preventDefault()
// 获取鼠标与拖拽盒子的偏移量(确保鼠标始终在点击盒子时的地位)const boxX = event.clientX - el.offsetLeft
const boxY = event.clientY - el.offsetTop
// 计算极限偏移量
const maxX = parentEl.offsetWidth - el.offsetWidth
const maxY = parentEl.offsetHeight - el.offsetHeight
// 获取拖拽元素的初始定位层级
const el_style = window.getComputedStyle(el, null)
const origin_zIndex = el_style.zIndex
const origin_cursor = el_style.cursor
el.style.zIndex = '9999'
el.style.cursor = 'move'
document.onmousemove = (event) => {
// 获取鼠标以后的地位
const mouseX = event.clientX
const mouseY = event.clientY
// 计算被拖拽盒子的偏移量
let moveX = mouseX - boxX
let moveY = mouseY - boxY
// 限度盒子的推拽范畴
moveX < 0 && (moveX = 0)
moveY < 0 && (moveY = 0)
moveX > maxX && (moveX = maxX)
moveY > maxY && (moveY = maxY)
// 赋予待拖拽的盒子新地位
el.style.left = moveX + 'px'
el.style.top = moveY + 'px'
}
document.onmouseup = (event) => {
// 还原初始层级 && 鼠标款式
el.style.zIndex = origin_zIndex
el.style.cursor = origin_cursor
document.onmousemove = null
document.onmouseup = null
}
}
},
},
},
})
</script>
</body>
</html>