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 相关文章推荐
游戏人文件夹程序 ver 4.03
Jul 14 Javascript
Ext.MessageBox工具类简介
Dec 10 Javascript
javascript验证身份证完全方法具体实现
Nov 18 Javascript
javascript实现存储hmtl字符串示例
Apr 25 Javascript
使用jQuery或者原生js实现鼠标滚动加载页面新数据
Mar 06 Javascript
jQuery的Cookie封装,与PHP交互的简单实现
Oct 05 Javascript
JS获取多维数组中相同键的值实现方法示例
Jan 06 Javascript
字太多用...代替的方法(两种)
Mar 15 Javascript
VueJs 搭建Axios接口请求工具
Nov 20 Javascript
详解vue挂载到dom上会发生什么
Jan 20 Javascript
微信小程序页面上下滚动效果
Nov 18 Javascript
vue在路由中验证token是否存在的简单实现
Nov 11 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中DOMDocument简单用法示例代码(XML创建、添加、删除、修改)
2010/12/19 PHP
ThinkPHP 连接Oracle数据库的详细教程[全]
2012/07/16 PHP
ThinkPHP的模版中调用session数据的方法
2014/07/01 PHP
你真的了解JavaScript吗?
2007/02/24 Javascript
用prototype实现的简单小巧的多级联动菜单
2007/03/24 Javascript
Javascript连接多个数组不用concat来解决
2014/03/24 Javascript
jQuery中wrapAll()方法用法实例
2015/01/16 Javascript
浅析Bootstrap验证控件的使用
2016/06/23 Javascript
详解javascript 正则表达式之分组与前瞻匹配
2018/05/30 Javascript
解决使用bootstrap的dropdown部件时报错:error:Bootstrap dropdown require Popper.js问题
2018/08/30 Javascript
浅析Vue.js中v-bind v-model的使用和区别
2018/12/04 Javascript
了解重排与重绘
2019/05/29 Javascript
简单实现节流函数和防抖函数过程解析
2019/10/08 Javascript
使用JS实现动态时钟
2020/03/12 Javascript
autojs 蚂蚁森林能量自动拾取即给指定好友浇水的实现方法
2020/05/03 Javascript
微信小程序学习总结(二)样式、属性、模板操作分析
2020/06/04 Javascript
javascript使用正则表达式实现注册登入校验
2020/09/23 Javascript
Python Sleep休眠函数使用简单实例
2015/02/02 Python
Windows下Python的Django框架环境部署及应用编写入门
2016/03/10 Python
Python切片索引用法示例
2018/05/15 Python
如何为Python终端提供持久性历史记录
2019/09/03 Python
Keras设定GPU使用内存大小方式(Tensorflow backend)
2020/05/22 Python
Python爬虫设置Cookie解决网站拦截并爬取蚂蚁短租的问题
2021/02/22 Python
Bose加拿大官方网站:美国知名音响品牌
2019/03/21 全球购物
教师实习期自我鉴定
2013/10/06 职场文书
公司财务工作总结的自我评价
2013/11/23 职场文书
办公室员工岗位工作职责
2014/03/10 职场文书
护理目标管理责任书
2014/07/25 职场文书
法人单位授权委托书范文
2014/10/06 职场文书
2015年乡镇残联工作总结
2015/05/13 职场文书
婚礼迎宾词大全
2015/08/10 职场文书
生鲜超市—未来中国最具有潜力零售业态
2019/08/02 职场文书
python 实现定时任务的四种方式
2021/04/01 Python
MySQL之DML语言
2021/04/05 MySQL
浅谈Python numpy创建空数组的问题
2021/05/25 Python
Python批量解压&压缩文件夹的示例代码
2022/04/04 Python