描述
在项目中,可能某些元素我们要实现可拖拽的要求,刚好使用Vue开发,Vue有一个很好用的东西,叫做自定义指令。后面想了想,可以把这个功能做成自定义指令,哪个元素想用,就绑定上去就好了,方便简单明了。至于后面的遍历注册很简单,就是一个forEach循环,使我们的代码更简洁,因为我们项目中可能不止定义一个自定义指令,所以也算一个小小的优化。
看之前也可以去看下官方文档的自定义指令
https://cn.vuejs.org/v2/guide/custom-directive.html
效果
先看下效果图,实现了拖拽功能,因为上传GIF图有大小限制,只演示了限制一边,实际上四边全部限制了超出。
代码
首先,新建一个utils文件夹,在里面新建一个directive.js文件。把我们的自定义指令放在这个文件里面。
实现拖拽指令的逻辑也比较简单,首先我们在touchstart事件中,记录元素最开始的位置,然后在touchmove中,监听我们的手指位置,动态的改变元素的top和left的值,就可以实现元素跟随我们的手指移动了。最后加一个判断,使元素不可以超出我们的屏幕范围之外。
export default {
//这个是自动获取焦点,拿过来展示循环注册自定义指令的
focus: {
inserted: function(el) {
// 聚焦元素
el.focus()
}
},
//拖拽指令
drag: {
//这个el就是我们绑定的那个元素
inserted: function(el) {
// 页面可用高度
let pageHeight = window.screen.availHeight
let pageWidth = window.screen.availWidth
// 初始位置
let touchstartX = 0
let touchstartY = 0
// 元素的宽高的一半
let elWidth = el.clientWidth / 2
let elHeight = el.clientHeight / 2
el.style.position = 'fixed'
el.addEventListener('touchstart', function(e) {
// 相对于可视区域的位置,记录最开始的位置
touchstartX = e.targetTouches[0].clientX
touchstartY = e.targetTouches[0].clientY
})
el.addEventListener('touchmove', function(e) {
// 相对于可视区域的位置
let newTouchstartX = e.targetTouches[0].clientX
let newTouchstartY = e.targetTouches[0].clientY
//这里也可以判断的更精细点,我这里处理的比较粗糙
if (newTouchstartX > elWidth && newTouchstartY > elHeight && newTouchstartY <= pageHeight - elHeight && newTouchstartX <= pageWidth - elWidth) {
el.style.left = touchstartX + (newTouchstartX - touchstartX) - elWidth + 'px';
el.style.top = touchstartY + (newTouchstartY - touchstartY) - elHeight + 'px';
}
})
}
}
}
写好我们的自定义指令后,就是注册了,我这边直接注册全局自定义指令,在main.js文件中,导入写好的js文件,循环遍历下。到这里我们的操作就结束了。
import directive from './utils/directive'
Object.keys(directive).forEach(key => {
Vue.directive(key, directive[key]);
});
使用的话,直接v-focus
、v-drag
就好了
<input v-focus type="text" name="" id="">
<div v-drag></div>
写完后,拖拽的时候也没有导致页面滚动事件,所以我也没有对页面滚动进行禁止。
如果想禁止的话,Vue提供了一些属性,@touchmove.prevent
.prevent是VUE里的事件修饰符,用来阻止默认事件,相当于 event.preventDefault()
个人水平有限,有问题欢迎大家留言指导,仅供学习和参考。
学海无涯!努力二字,共勉!