不熟悉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. 基于C++11的100行实现简单线程池

    基于C++11的100行实现简单线程池 1 线程池原理 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线程池线程都是后台线程.每个线程都使用默认的堆栈大小, ...

  2. YOLO---Darknet下的学习笔记

    YOLO.V3-Darknet下的学习笔记 @wp20180927 [目录] 一. 安装Darknet(仅CPU下) 2 1.1在CPU下安装Darknet方式 2 1.2在GPU下安装Darknet ...

  3. 6.caffe:create_txt.sh(数据预处理成txt文本文件)

    #!/usr/bin/env sh DATA=/home/wp/CAFFE/caffe-master/myself/00b MY=/home/wp/CAFFE/caffe-master/myself/ ...

  4. Loadrunner12-思考时间设置

    1.什么是思考时间 简单来说就是可以在不同的操作之间做停顿,最大程度的模拟用户最真实的操作. 2.如何设置思考时间 函数:lr_think_time(4) 进入Runtime Settings页面,快 ...

  5. Java Listener

    六.  Java Listener 1.  Java Listener 简介 * Java Listener 1. Java Listener(即:Java 监听器):用于监听 ServletRequ ...

  6. Golang对方法接收者变量的自动“取引用”和“解引用”

    原文:https://blog.csdn.net/u014633283/article/details/83826413 --------------------------------------- ...

  7. 数据库 Redis:Windows环境安装

    1. 下载 Redis (1)前往 GitHub 下载:https://github.com/microsoftarchive/redis (2)点击 release : (3)选择好版本号后,下载文 ...

  8. Unity 连接WebSocket(ws://)服务器

    Unity 连接ws,不用任何插件,忙活了一天终于搞定了,一直连接不上,原来是没有添加header, 代码比较简单,直接贴出来普度众生 using System; using System.Net.W ...

  9. 题解 [CF332C] Students' Revenge

    题面 解析 辣鸡题面毁我青春 因为翻译的题面中写了一句\(剩下的n−k个不会完成\). 所以就以为剩下的\(n-k\)个都会算上不满意值. (然而事实是只有\(p-k\)个...) 首先根据主席的规则 ...

  10. spring@Async注解实现异步方法调用

    概述 如何实现异步方法调用,很多人首先会想到使用线程或者线程池技术,springboot中有一个很简单的方法可以实现异步方法调用,那就是在方法上使用@Async注解 例子 首先在Springboot启 ...