Vue使用自定义指令实现拖拽行为实例分析


Posted in Javascript onJune 06, 2020

本文实例讲述了Vue使用自定义指令实现拖拽行为。分享给大家供大家参考,具体如下:

需求

通过自定义指令的方式实现拖拽效果,预期的使用方式为:

<div style="background: #f00; width: 200px; height: 200px;" v-drag>
  XXXX
</div>

更重要的一个需求点:

  • 拖拽元素内部的子元素可以自行阻止拖拽行为

比如:

<div style="background: #f00; width: 200px; height: 200px;" v-drag>
   <el-button @mousedown.native.stop>test</el-button>
</div>

曾经使用过vue-resizable,由于该组件是通过事件捕获的方式实现的,拖拽元素的子元素也会触发拖拽行为,不符合开发需求,所以自行实现了拖拽指令,相关源码如下。

无任何依赖,复制即可使用

源码

/**
 * @file 自定义拖拽命令
 */
import Vue from 'vue';
const Drag = {
  install(Vue: any) {
    // 如需禁止拖拽元素内部某些元素触发拖拽,在内部不可触发拖拽元素上添加@mousedown.native.stop即可
    Vue.directive('drag', {
      bind(el: any) {
        el.style.position = 'absolute';
        el.style.zIndex = el.style.zIndex || '3000';
      },

      inserted(el: any) {
        // 设置元素初始位置
        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__);
        // 当父组件销毁触发unbind的时候需要手动删除这个节点,不然会一直存留在body中
        el.parentNode.removeChild(el);
      }
    });
  }
};
Vue.use(Drag);
export default Drag;

希望本文所述对大家vue.js程序设计有所帮助。

Javascript 相关文章推荐
JavaScript 格式字符串的应用
Mar 29 Javascript
js修改地址栏URL参数解决url参数问题
Dec 15 Javascript
js关闭浏览器窗口及检查浏览器关闭事件
Sep 03 Javascript
moment.js轻松实现获取当前日期是当年的第几周
Feb 05 Javascript
JavaScript日期类型的一些用法介绍
Mar 02 Javascript
javascript获取当前的时间戳的方法汇总
Jul 26 Javascript
深入分析Javascript事件代理
Jan 30 Javascript
Vue.js基础知识小结
Jan 13 Javascript
vue组件实现文字居中对齐的方法
Aug 23 Javascript
使用原生js编写一个简单的框选功能方法
May 13 Javascript
vue v-model的用法解析
Oct 19 Javascript
vue中 this.$set的使用详解
Nov 17 Vue.js
JS原型对象操作实例分析
Jun 06 #Javascript
JS中的继承操作实例总结
Jun 06 #Javascript
ES6 async、await的基本使用方法示例
Jun 06 #Javascript
JS 数组和对象的深拷贝操作示例
Jun 06 #Javascript
ES6 Generator基本使用方法示例
Jun 06 #Javascript
jquery.validate自定义验证用法实例分析【成功提示与择要提示】
Jun 06 #jQuery
ES6 Symbol在对象中的作用实例分析
Jun 06 #Javascript
You might like
数据库查询记录php 多行多列显示
2009/08/15 PHP
php学习之流程控制实现代码
2011/06/09 PHP
一致性哈希算法以及其PHP实现详细解析
2013/08/24 PHP
ThinkPHP路由机制简介
2016/03/23 PHP
Yii2基于Ajax自动获取表单数据的方法
2016/08/10 PHP
php如何利用pecl安装mongodb扩展详解
2019/01/09 PHP
js 表单验证方法(实用)
2009/04/28 Javascript
基于jQuery的图片左右无缝滚动插件
2012/05/23 Javascript
JavaScript中神奇的call()方法
2015/03/12 Javascript
表格展示利器 Bootstrap Table实例代码
2017/09/06 Javascript
JavaScript实现重力下落与弹性效果的方法分析
2017/12/20 Javascript
vue路由--网站导航功能详解
2019/03/29 Javascript
layer 关闭指定弹出层的例子
2019/09/25 Javascript
使用Python标准库中的wave模块绘制乐谱的简单教程
2015/03/30 Python
python使用fcntl模块实现程序加锁功能示例
2017/06/23 Python
Python金融数据可视化汇总
2017/11/17 Python
selenium设置proxy、headers的方法(phantomjs、Chrome、Firefox)
2018/11/29 Python
Python 判断奇数偶数的方法
2018/12/20 Python
用python求一个数组的和与平均值的实现方法
2019/06/29 Python
Python Pandas对缺失值的处理方法
2019/09/27 Python
Python中的 ansible 动态Inventory 脚本
2020/01/19 Python
如何定义TensorFlow输入节点
2020/01/23 Python
Python引入多个模块及包的概念过程解析
2020/09/21 Python
Stefania Mode英国:奢华设计师和时尚服装
2017/10/23 全球购物
俄罗斯童装网上商店:BebaKids
2020/06/06 全球购物
物业管理公司实习生自我鉴定
2013/09/19 职场文书
企业治理工作自我评价
2013/09/26 职场文书
个人求职简历中英文自我评价
2013/12/16 职场文书
文艺演出策划方案
2014/06/07 职场文书
婚内房产协议书范本
2014/10/02 职场文书
2014年党风廉政工作总结
2014/12/03 职场文书
工作试用期自我评价
2015/03/10 职场文书
关于军训的感想
2015/08/07 职场文书
MySQL8.0无法启动3534的解决方法
2021/06/03 MySQL
TypeScript 使用 Tuple Union 声明函数重载
2022/04/07 Javascript
JS实现简单的九宫格抽奖
2022/06/28 Javascript