总结一些日常需要用到的一些api,也是在一些面试中会经常出现的题目,今天分享的是vue3中使用自定义指令封装拖拽方法, 同时文章也被收录到我的《JS基础》专栏中,欢迎大家点击收藏加关注。
vue指令
vue中有内置的一些指令供我们使用,
v-model
或v-show
是比较常见的指令,绑定在对应的元素上,可以对元素的样式或者值进行一些对应的JS操作,除了vue内置的一些指令之外,如果业务需要,我们也会书写一些自己的自定义指令,自定义指令主要是为了重用涉及普通元素的底层 DOM 访问的逻辑,也就是封装一些对dom的操作
今天在项目中使用自定义指令写一个拖拽操作,主要记录一下实现的过程,局部挂载和全局挂载的区别,由于生命周期大部份情况下都可能用不到,所以我们只记录下mouted生命周期的绑定。
局部挂载
在 <script setup>
中,任何以 v
开头的驼峰式命名的变量都可以被用作一个自定义指令。在下面的例子中,vDrag
即可以在模板中以 v-drag
的形式使用
这里大概说下指令内的内容,声明一个名为vDrag的指令,犹豫vDrag是绑定在元素上的,所以mounted表示元素在绑定元素的父组件及他自己的所有子节点都挂载完成后调用
,调用的时候传入el,el是绑定的dom元素
// layout.vue
<script setup lang="ts">
const vDrag = {mounted: (el :HTMLElement) => {console.log(el)el.style.cursor = 'grab';el.onmousedown=(e)=>{document.onmousemove = function (e) {e.preventDefault(); // 移动时禁用默认事件 否则拖动的时候会有将元素拖动出来的效果// 计算偏移距离 鼠标x - 元素xlet left = e.clientX - el.offsetLeftlet sider:HTMLElement = document.querySelector('.n-layout-sider')! //不能将类型“HTMLElement | null”分配给类型“HTMLElement” 这里可以使用断言sider.style.width = el.offsetLeft + left + 'px'console.log(el.offsetLeft + left )// console.log('clientX',e.clientX)// console.log('offsetLeft',el.offsetLeft) //元素和屏幕的左边距}document.onmouseup = function () { //按压时间结束的时候 要禁用掉down的监听事件 否则会一直执行document.onmousemove = null;document.onmouseup = null;};}}
}
</script>
<template>...<div class="line" v-drag ></div>...
</template>
接下来是一系列的实现拖拽的代码,mounted的时候改变鼠标悬浮效果,接着按下鼠标禁用默认事件,监听鼠标x轴上的移动距离,减掉元素宽度,由于要实现宽度拖拽,所以要改变的其实是n-layout-sider
的宽度,这部分还不够完善,大家仅供参考,最后是鼠标抬起事件,将前面的监听事件down和up取消掉,否则会一直监听。
具体效果
这里我对n-layout-sider
的宽度在css规定了最小和最大宽度,所以拖动到左边的时候会有限制。
全局挂载
全局中进行使用,这里只要把封装好的指令进行引入,再通过directive挂载到app上,需要注意的是,不同于局部挂载的写法,这里应该写的是’move’而不是’v-move’,因为这是通过directive函数来进行挂载指令,所以只需要写上指令的名称
//widthMove.ts
export constvMove = {
mounted: (el :HTMLElement) => { ....
}
}
import{vMove}from "@/utils/widthMove.js";
const app = createApp(App)
app.directive('move',vMove) //
app.mount('#app')
最后
为大家准备了一个前端资料包。包含54本,2.57G的前端相关电子书,《前端面试宝典(附答案和解析)》,难点、重点知识视频教程(全套)。
有需要的小伙伴,可以点击下方卡片领取,无偿分享