vue自定义指令之面板拖拽的实现


Posted in Javascript onApril 14, 2019

前言

在指令里获取的this并不是vue对象,vnode.context才是vue对象,一般来说,指令最好不要访问vue上的data,以追求解耦,但是可以通过指令传进来的值去访问method或ref之类的。

vue指令

官方文档其实已经解释的蛮清楚了,这里挑几个重点的来讲。

1、arguments

el: 当前的node对象,用于操作dom
binding:模版解析之后的值
vNode: Vue 编译生成的虚拟节点,可以在上面获取vue对象
oldVnode: 使用当前指令上一次变化的node内容

2、 生命周期

bind: 初始化的时候调用,但这时候node不一定渲染完成
inserted: 被绑定元素插入父节点时调用,关于dom操作尽量在这里用
update:就是内部this.update时会触发这里

面板拖拽逻辑

使用relative,舰艇event上的clientX和clientY鼠标距离页面的位置来改变面板的top和left。

涉及属性

  • offsetLeft:距离参照元素左边界偏移量
  • offsetTop:距离参照元素上边界偏移量
  • clientWidth:此属性可以返回指定元素客户区宽度
  • clientHeight: 此属性可以返回指定元素客户区高度
  • clientX:事件被触发时鼠标指针相对于浏览器页面(或客户区)的水平坐标
  • clientY: 事件被触发时鼠标指针相对于浏览器页面(或客户区)的垂直坐标
  • onmousedown:鼠标按下事件
  • onmousemove: 鼠标滑动事件
  • onmouseup: 鼠标松开事件

实现代码

<div v-drag="'refName'"></div>

在绑定的组件上使用,value非必选项,不挑就默认是基于document的移动

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;
     };
    };
   }
  }
 }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JS 动态获取节点代码innerHTML分析 [IE,FF]
Nov 30 Javascript
两个JavaScript jsFiddle JSBin在线调试器
Mar 14 Javascript
基本jquery的控制tabs打开的数量的代码
Oct 17 Javascript
jquery改变tr背景色的示例代码
Dec 28 Javascript
js转化毫秒为时间格式代码
Apr 10 Javascript
JavaScript原生对象之String对象的属性和方法详解
Mar 13 Javascript
基于jquery实现导航菜单高亮显示(两种方法)
Aug 23 Javascript
JavaScript自定义函数实现查找两个字符串最长公共子串的方法
Nov 24 Javascript
Node批量爬取头条视频并保存方法
Sep 20 Javascript
从源码里了解vue中的nextTick的使用
Nov 22 Javascript
Vue学习笔记之计算属性与侦听器用法
Dec 07 Javascript
JavaScript获取时区实现过程解析
Sep 24 Javascript
详解Vue组件之间通信的七种方式
Apr 14 #Javascript
浅谈Vue CLI 3结合Lerna进行UI框架设计
Apr 14 #Javascript
vue使用axios上传文件(FormData)的方法
Apr 14 #Javascript
详解如何理解vue的key属性
Apr 14 #Javascript
axios+Vue实现上传文件显示进度功能
Apr 14 #Javascript
Vue 使用formData方式向后台发送数据的实现
Apr 14 #Javascript
说说如何使用Vuex进行状态管理(小结)
Apr 14 #Javascript
You might like
PHP中一个控制字符串输出的函数
2006/10/09 PHP
浅谈PHP 闭包特性在实际应用中的问题
2009/10/30 PHP
PHP 数组排序方法总结 推荐收藏
2010/06/30 PHP
探讨PHP调用时间格式的参数详解
2013/06/06 PHP
使用PHP访问RabbitMQ消息队列的方法示例
2018/06/06 PHP
浅谈JavaScript中定义变量时有无var声明的区别
2014/08/18 Javascript
jQuery中extend()和fn.extend()方法详解
2015/06/03 Javascript
jQuery Timelinr实现垂直水平时间轴插件(附源码下载)
2016/02/16 Javascript
原生js实现autocomplete插件
2016/04/14 Javascript
实例解析angularjs的filter过滤器
2016/12/14 Javascript
详解vue嵌套路由-params传递参数
2017/05/23 Javascript
Vue实现web分页组件详解
2017/11/28 Javascript
VueJs使用Amaze ui调整列表和内容页面
2017/11/30 Javascript
Angular中点击li标签实现更改颜色的核心代码
2017/12/08 Javascript
react+ant design实现Table的增、删、改的示例代码
2018/12/27 Javascript
vue插槽slot的理解和使用方法
2019/04/03 Javascript
vue实现列表滚动的过渡动画
2020/06/29 Javascript
Vue作用域插槽实现方法及作用详解
2020/07/08 Javascript
Vue如何基于vue-i18n实现多国语言兼容
2020/07/17 Javascript
Openlayers绘制地图标注
2020/09/28 Javascript
Vue中引入svg图标的两种方式
2021/01/14 Vue.js
[04:36]DOTA2国际邀请赛 ti3精彩集锦
2013/08/19 DOTA
Python做简单的字符串匹配详解
2017/03/21 Python
python3之模块psutil系统性能信息使用
2018/05/30 Python
使用APScheduler3.0.1 实现定时任务的方法
2019/07/22 Python
python_matplotlib改变横坐标和纵坐标上的刻度(ticks)方式
2020/05/16 Python
python中uuid模块实例浅析
2020/12/29 Python
CSS3悬停效果案例应用
2012/11/21 HTML / CSS
美国著名的品牌折扣店:Burlington
2017/06/08 全球购物
女性时尚在线:IVRose
2019/02/23 全球购物
勾股定理课后反思
2014/04/26 职场文书
社会实践活动总结范文
2014/07/03 职场文书
党的群众路线教育实践活动对照检查剖析材料
2014/10/09 职场文书
德能勤绩廉个人总结
2015/02/14 职场文书
Python如何识别银行卡卡号?
2021/06/10 Python
Java新手教程之ArrayList的基本使用
2021/06/20 Java/Android