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

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

Vue.directives: {
drag: {
// 使用bind会有可能没有渲染完成
inserted: function(el, binding, vnode) {
const _el = el; //获取当前元素
const ref = vnode.context.$refs[binding.value]; // 判断基于移动的是哪一个盒子
const masterNode = ref ? ref : document; // 用于绑定事件
const masterBody = ref ? ref : document.body; // 用于获取高和宽
const mgl = _el.offsetLeft;
const mgt = _el.offsetTop;
const maxWidth = masterBody.clientWidth;
const maxHeight = masterBody.clientHeight;
const elWidth = _el.clientWidth;
const elHeight = _el.clientHeight;
let positionX = 0,
positionY = 0;
_el.onmousedown = e => {
//算出鼠标相对元素的位置,加上的值是margin的值
let disX = e.clientX - _el.offsetLeft + mgl;
let disY = e.clientY - _el.offsetTop + mgt;
masterNode.onmousemove = e => {
//用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
let left = e.clientX - disX;
let top = e.clientY - disY;
// 绑定的值不能滑出基于盒子的范围
left < 0 && (left = 0);
left > (maxWidth - elWidth - mgl) && (left = maxWidth - elWidth - mgl);
top < 0 && (top = 0);
top > (maxHeight - elHeight - mgt) && (top = maxHeight - elHeight - mgt);
//绑定元素位置到positionX和positionY上面
positionX = top;
positionY = left; //移动当前元素
_el.style.left = left + "px";
_el.style.top = top + "px";
};
// 这里是鼠标超出基于盒子范围之后再松开,会监听不到
document.onmouseup = e => {
masterNode.onmousemove = null;
document.onmouseup = null;
};
};
}
}
}

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

Vue.directive('drag', {
bind (el, binding) {
el.style.cursor = 'move'
el.style.position = 'fixed'
el.mousedownPoint = {
x: 0,
y: 0
}
// bind 改变函数内部 this 指向,让 this 指向 el
// el.handleMouseup, el.handleMousemove, el.handleMousedown 这三个可以是其他的全局变量
el.handleMouseup = handleMouseup.bind(el)
el.handleMousemove = handleMousemove.bind(el)
el.handleMousedown = handleMousedown.bind(el)
el.addEventListener('mousedown', el.handleMousedown)
document.body.addEventListener('mouseup', el.handleMouseup)
document.body.addEventListener('mousemove', el.handleMousemove)
},
unbind (el) {
document.body.removeEventListener('mouseup', el.handleMouseup)
document.body.removeEventListener('mousemove', el.handleMousemove)
}
});
const handleMousedown = function (e) {
// 这里的this被bind改变了,是el
// 这里的e是 MouseEvent 对象
const initialPosition = this.getBoundingClientRect()
this.style.width = initialPosition.width + 'px'
this.position = {
left: initialPosition.left,
top: initialPosition.top
}
this.readyToMove = true
this.mousedownPoint.x = e.screenX
this.mousedownPoint.y = e.screenY
}
const handleMousemove = function (e) {
if (!this.readyToMove) return false
const position = this.position
position.left = position.left + e.screenX - this.mousedownPoint.x
position.top = position.top + e.screenY - this.mousedownPoint.y
this.mousedownPoint.x = e.screenX
this.mousedownPoint.y = e.screenY
this.style.left = position.left + 'px'
this.style.transform = 'none'
this.style.marginLeft = 0
this.style.marginTop = 0
this.style.top = position.top + 'px'
this.style.bottom = 'auto'
this.style.right = 'auto'
}
const handleMouseup = function (e) {
this.readyToMove = false
}

这种写法主要利用了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. Django学习:连接Mysql数据库

    开发环境: Windows 10 Python 3.7.4 Django 2.2.6 Mysql 8.0.17 承接上一节:https://www.cnblogs.com/daydayupup/p/1 ...

  2. HDU - 3506 Monkey Party

    HDU - 3506 思路: 平行四边形不等式优化dp 这不就是石子归并(雾 代码: #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma G ...

  3. 关于C++编译时内链接和外链接

      最近在阅读<大规模C++ 程序设计> 在第1部分,作者讨论了内链接和外链接问题(因为大规模的C++程序有繁多的类和单元.因此编译速度是个大问题) 这里记录一下关于内链接和外链接的理解. ...

  4. Linux之df磁盘信息

    df命令用于查看磁盘的分区,磁盘已使用的空间,剩余的空间 1.用法 df [选项] [文件..] 2.命令选项 -a,--all 全部文件系统-h,--human-readable 以以合适的单位来显 ...

  5. CF666E Forensic Examination——SAM+线段树合并+倍增

    RemoteJudge 题目大意 给你一个串\(S\)以及一个字符串数组\(T[1...m]\),\(q\)次询问,每次问\(S\)的子串\(S[p_l...p_r]\)在\(T[l...r]\)中的 ...

  6. 在laravel5.8中集成swoole组件----用协程实现的服务端和客户端(二)---静态文件如何部署

    目前,较为成熟的技术是采用laravelS组件,注意和laravel 区别laravelS多了一个大写的S,由于laravelS默认监听5200端口,所以laravel项目要做一些调整 例如: 静态文 ...

  7. 05 django组件:contenttype

    1.django组件:contenttype 组件的作用:可以通过两个字段让表和N张表创建FK关系 1.专题课,学位课 如何关联 过期时间?? 方法1:分别创建 专题课--过期时间表 .学位课--过期 ...

  8. [Javascript] Customize Behavior when Accessing Properties with Proxy Handlers

    A Proxy allows you to trap what happens when you try to get a property value off of an object and do ...

  9. Visual Studio 查看宏展开

    使用Visual Studio 开发c++项目,中遇到项目中宏定义套宏定义,难以阅读源代码的时候. 可在 项目-->右键-->配置属性-->c/c++ -->预处理器 --&g ...

  10. PHP mysqli_fetch_array() 函数

    从结果集中取得一行作为数字数组或关联数组: <?php // 假定数据库用户名:root,密码:123456,数据库:RUNOOB $con=mysqli_connect("local ...