不熟悉vue自定义指令看这里: https://cn.vuejs.org/v2/guide/custom-directive.html

vue指令实现拖动方法很方便也挺简单,但是网上大部分的教程代码,一般都是把代码全部写一个方法里面,代码不够美观,代码逻辑也不太清晰,不推荐这种写法,比如下面这样:

  1. Vue.directives: {
  2. drag: {
  3. // 使用bind会有可能没有渲染完成
  4. inserted: function(el, binding, vnode) {
  5. const _el = el; //获取当前元素
  6. const ref = vnode.context.$refs[binding.value]; // 判断基于移动的是哪一个盒子
  7. const masterNode = ref ? ref : document; // 用于绑定事件
  8. const masterBody = ref ? ref : document.body; // 用于获取高和宽
  9. const mgl = _el.offsetLeft;
  10. const mgt = _el.offsetTop;
  11. const maxWidth = masterBody.clientWidth;
  12. const maxHeight = masterBody.clientHeight;
  13. const elWidth = _el.clientWidth;
  14. const elHeight = _el.clientHeight;
  15. let positionX = 0,
  16. positionY = 0;
  17. _el.onmousedown = e => {
  18. //算出鼠标相对元素的位置,加上的值是margin的值
  19. let disX = e.clientX - _el.offsetLeft + mgl;
  20. let disY = e.clientY - _el.offsetTop + mgt;
  21. masterNode.onmousemove = e => {
  22. //用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
  23. let left = e.clientX - disX;
  24. let top = e.clientY - disY;
  25. // 绑定的值不能滑出基于盒子的范围
  26. left < 0 && (left = 0);
  27. left > (maxWidth - elWidth - mgl) && (left = maxWidth - elWidth - mgl);
  28. top < 0 && (top = 0);
  29. top > (maxHeight - elHeight - mgt) && (top = maxHeight - elHeight - mgt);
  30. //绑定元素位置到positionX和positionY上面
  31. positionX = top;
  32. positionY = left;
  33.  
  34. //移动当前元素
  35. _el.style.left = left + "px";
  36. _el.style.top = top + "px";
  37. };
  38. // 这里是鼠标超出基于盒子范围之后再松开,会监听不到
  39. document.onmouseup = e => {
  40. masterNode.onmousemove = null;
  41. document.onmouseup = null;
  42. };
  43. };
  44. }
  45. }
  46. }

这里介绍一种比较方美观,逻辑清晰的写法,代码如下:

  1. Vue.directive('drag', {
  2. bind (el, binding) {
  3. el.style.cursor = 'move'
  4. el.style.position = 'fixed'
  5. el.mousedownPoint = {
  6. x: 0,
  7. y: 0
  8. }
  9. // bind 改变函数内部 this 指向,让 this 指向 el
  10. // el.handleMouseup, el.handleMousemove, el.handleMousedown 这三个可以是其他的全局变量
  11. el.handleMouseup = handleMouseup.bind(el)
  12. el.handleMousemove = handleMousemove.bind(el)
  13. el.handleMousedown = handleMousedown.bind(el)
  14. el.addEventListener('mousedown', el.handleMousedown)
  15. document.body.addEventListener('mouseup', el.handleMouseup)
  16. document.body.addEventListener('mousemove', el.handleMousemove)
  17. },
  18. unbind (el) {
  19. document.body.removeEventListener('mouseup', el.handleMouseup)
  20. document.body.removeEventListener('mousemove', el.handleMousemove)
  21. }
  22. });
  1. const handleMousedown = function (e) {
  2. // 这里的this被bind改变了,是el
  3. // 这里的e是 MouseEvent 对象
  4. const initialPosition = this.getBoundingClientRect()
  5. this.style.width = initialPosition.width + 'px'
  6. this.position = {
  7. left: initialPosition.left,
  8. top: initialPosition.top
  9. }
  10. this.readyToMove = true
  11. this.mousedownPoint.x = e.screenX
  12. this.mousedownPoint.y = e.screenY
  13. }
  14. const handleMousemove = function (e) {
  15. if (!this.readyToMove) return false
  16. const position = this.position
  17. position.left = position.left + e.screenX - this.mousedownPoint.x
  18. position.top = position.top + e.screenY - this.mousedownPoint.y
  19. this.mousedownPoint.x = e.screenX
  20. this.mousedownPoint.y = e.screenY
  21. this.style.left = position.left + 'px'
  22. this.style.transform = 'none'
  23. this.style.marginLeft = 0
  24. this.style.marginTop = 0
  25. this.style.top = position.top + 'px'
  26. this.style.bottom = 'auto'
  27. this.style.right = 'auto'
  28. }
  29. const handleMouseup = function (e) {
  30. this.readyToMove = false
  31. }

这种写法主要利用了bind的特性,回一个新的函数,并且这个函数的 this 已经被改成我们想要的 this, 推荐这种写法。

vue指令实现拖动的高级写法的更多相关文章

  1. 一个能拖动,能调整大小,能更新bind值的vue指令-vuedragx

    一. 背景说明 开发一个可自定义组件化门户配置页面,期间采用了vue框架作为前端视图引擎,作为一个刚入手vue的萌新,开发第一个功能就遇到了拦路虎.需要一个拖动并且可改变大小的容器盒子.当时查看vue ...

  2. 自定义类似于Jquery UI Selectable 的Vue指令v-selectable

    话不多说,先看效果. 其实就是一个可以按住鼠标进行一个区域内条目选择的功能,相信用过Jquery UI 的都知道这是selectable的功能,然而我们如果用Vue开发的话没有类似的插件,当然你仍然可 ...

  3. vue指令用法

    vue指令 指令式带有 v- 前缀的特殊特性v-text和v-html都属于指令将数据和dom做关联,当表达式的值改变时,响应式地作用在视图 解决大胡子语法闪烁案例 [v-cloak] { dispa ...

  4. Vue框架(一)——Vue导读、Vue实例(挂载点el、数据data、过滤器filters)、Vue指令(文本指令v-text、事件指令v-on、属性指令v-bind、表单指令v-model)

    Vue导读 1.Vue框架 vue是可以独立完成前后端分离式web项目的js框架 三大主流框架之一:Angular.React.Vue vue:结合其他框架优点.轻量级.中文API.数据驱动.双向绑定 ...

  5. Vue学习笔记【4】——Vue指令之v-on

    Vue指令之v-on v-on指令介绍 直接使用指令v-on 使用简化指令@ 绑定事件代码:@事件名="methods中的方法名称" <!DOCTYPE html> & ...

  6. vue2,vue指令和选项

    vue特点 mvvm框架 响应式(声明式) 组件化(支持自定义组件) 丰富的指令(Dom功能的抽象) 基于选项(template,data,computed,watch,methods) vue文档集 ...

  7. Vue指令总结---小白同学必看

    今天主要复习一下我们最熟悉vue指令,想要代码撸得快,就要多看书,多看看官方的文档和学习指令,学习编程是一个非常享受的过程,尤其是你不断地去解决问题,获得一项技能,实现薪水的上涨.进行Vue的指令烹饪 ...

  8. 使用Vue.js制作仿Metronic高级表格(一)静态设计

    Metronic高级表格是Metonic框架中自行实现的表格,其底层是Datatables.本教程将主要使用Vue实现交互部分,使用Bootstrap做样式库.jQuery做部分用户交互(弹窗). 使 ...

  9. vue+mousemove实现拖动,鼠标移动过快拖动就失效

    今天用vue+原生js的mousemove事件,写了个拖动,发现只能慢慢拖动才行,鼠标只要移动快了,就失效,不能拖动了: 搞了半天在,总算解决了,但是问题的深层原理还没搞清楚,知道的大侠可以留言分享, ...

随机推荐

  1. [shell] shell echo打印换行的方法

    echo要支持同C语言一样的\转义功能,只需要加上参数-e,如下所示: echo -e hello \n echo \n

  2. java线程基础巩固---采用多线程方式模拟银行排队叫号以及Runnable接口存在的必要性

    采用多线程模拟银行排队叫号: 关于银行拿排队号去叫号的过程我想不必过多解释了,就是有几个业务窗口,并行的处理业务,每处里完一个人,则会叫下一个排队的号去处理业务,一个人是不会被多个窗口工作人员叫号的, ...

  3. django.core.exceptions.ImproperlyConfigured: The included URLconf 's9luffycity.urls' does not appear to have any patterns in it. If you see valid patterns in the file then the issue is probably caused

    出现问题: $ python manage.py runserver 启动项目报错时候 raise ImproperlyConfigured(msg.format(name=self.urlconf_ ...

  4. 部署lnmp

    装包 1.安装依赖包 yum - y install gcc openssl-devel pcre-devel zlib-devel 2.解源码包 .tar.gz 3.切换到解压缩后的目录,配置参数 ...

  5. MFC 线程的创建,线程函数在类内、类外

    [线程的创建] AfxBeginThread(类外的线程函数,NULL); AfxBeginThread(类内的线程函数,(LPVOID)this); [类外线程函数] UINT 函数名(LPVOID ...

  6. has(expr|ele)保留包含特定后代的元素,去掉那些不含有指定后代的元素。

    has(expr|ele) 概述 保留包含特定后代的元素,去掉那些不含有指定后代的元素.大理石平台等级 .has()方法将会从给定的jQuery对象中重新创建一组匹配的对象.提供的选择器会一一测试原先 ...

  7. learning armbian steps(9) ----- armbian 源码分析(四)

    在上一节的分析当中,我们知道是通过对话框来选择到底编译的是哪块板子,基于什么样的配置. 接下来我们来拿一个实例来分析一下具体的案例,我们会选中如下所示的版本 iotx-3 AM335X 1Gb SoC ...

  8. vector 与 array

    vector STL中的模板数组(在堆中分配内存空间,通过new delete管理内存) 使用包涵头文件#include <vector> vector<ElmentTpye> ...

  9. javascript数据结构之顺序表

    关于线性表的概念这里就不赘述了,可以自行百度和查阅资料,线性表按照存储(物理)结构分为顺序存储和链式存储,每种存储方式的不同决定了它的实现代码是不同的: 顺序存储的特点就是在内存中选一块连续的地址空间 ...

  10. sql到python正则

    import urllib.requestimport re,timeresult=[]for i in range(100):    urls ="http://xxx.com/-1%20 ...