一、 背景说明

开发一个可自定义组件化门户配置页面,期间采用了vue框架作为前端视图引擎,作为一个刚入手vue的萌新,开发第一个功能就遇到了拦路虎。需要一个拖动并且可改变大小的容器盒子。当时查看vue开发文档,查找github都没找到一个自己欢心的实现,所以与其求人,还不如求己。所以vuedragx这个轮子就有了,x代表它不止可拖动。
github地址:https://github.com/464884492/vuedragx

二、效果图

三、开发思路

  • 通过鼠标移动实现组件移动,改变大小,一定需要操作dom,查看vue官方文档,从实用性,已经通用性,选择开发一个自定义vue指令
  • 通过鼠标移动产生的位移,动态改变大小或位置
  • 通过事件通知方式,实现更新bind值

所以有了以上思路,就需要一次掌握三个重要知识

  1. vue 如果开发一个自定义指令
  2. 鼠标移动过程中,MouseEvent对象各种值的含义
  3. 如何使用并分发一个自定义事件

3.1 vue指令

记住,不管使用什么样的框架,需要学习某种技能,需要学习api各种方法的用法,最好的途径就是查看对应官方文档

vue 开发自定义指令地址 https://cn.vuejs.org/v2/guide/custom-directive.html
通读一篇,然后敲黑板画重点

  1. 什么时候使用Vue指令

官方是么说的 在 Vue2.0 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令

显而易见,通过需要使用鼠标产生的位移,通过啥啥实在是比较为难在下了

  1. 如何开发

针对vue指令,官方给开发这提供了几个勾子函数,来注入开发者开发的功能,所谓的钩子函数,个人理解也就是在正常的代码中插入预埋的未实现的函数接口

vue对开发着提供(bind、inserted、update、componentUpdated、unbind)注入点。

  • bind 只调用一次,指令第一次绑定到元素时调用,主要完成指令初始化设置
  • inserted 被绑定元素插入父节点时调用,官网对这里有一个强调 仅保证父节点存在,但不一定被插入文档中 个人认为这个保证父节点,是只存在与所谓的虚dom中,只是没有实际应用与真实的dom中,不知道这个理解是否正确?
  • update 所在组件的VNode更新时调用,但也可能发生在其子VNode更新之前,所以提供的参数中包含 vnode oldVnode,具体是否需要响应操作,可以比较这两个node中对应的值是否变化
  • componentUpdated 指令所在组件的 VNode极其子VNode全部更新后调用,此钩子函数的补充,就可以解决update钩子,不及时更新问题。
  • unbind 只调用一次,指令与元素解绑是调用

每一个钩子都带有参数 el、binding、vnode、oldVnode

  • el 当前绑定的dom
  • binding 对象,包含以下属性
    • name 指令名称,不过个人理解此参数感觉没有使用的场景
    • value 指令bind的值,如果是可运行的表达式,将返回计算结果。如果绑定的是一个对象,将返回此对象,vuedragx,采用此属性传入个性化配置信息。
    • oldValue 指令绑定的前一个值,仅在 update 和 componentUpdated 钩子函数中可用
    • expression 字符串形式的指令表达式,就是在代码开发中v-dragx=”A”,这个A就是表达式
    • arg 传给指令的参数,如 v-dragx:foo,参数为foo,注意标识符 :
    • modifiers 一个包含修饰符的对象,如:v-dragx.dragable.resizeable,修饰符对象为{dragable:true,resizeable:true},不过vuedragx并没有使用此方法传值,统一通过binding.value传值
    • vnode Vue 编译生成的虚拟节点
    • oldVnode 上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用

关于vue指令的钩子函数,参数等相关说明,基本从官网引用过来的。我觉得有必要再次在强调以下,使用第三方的框架,最好途径就是查阅官方文档。其次可以看看对应的源码,如果有的话。

3.2 MouseEvent

上边在vue指令介绍中,强调了查阅官方文档的重要性,那么针对javascript的api又该在那里查阅呢?当然是 MDN,没有第二

MDN中关于MouseEvent说明的地址: https://developer.mozilla.org/zh-CN/docs/Web/API/MouseEvent,开发vuedragx需要MouseEvent中最重要的两个属性MouseEvent.pageXMouseEvent.pageY

  • MouseEvent.pageX 相对于整个文档的x(水平)坐标。此属性包含了元素滚动的距离 ,官方解释为 这个属性将基于文档的边缘,考虑任何页面的水平方向上的滚动。举个例子,如果页面向右滚动 200px 并出现了滚动条,这部分在窗口之外,然后鼠标点击距离窗口左边 100px 的位置,pageX 所返回的值将是 300。

做为延伸,分别查看了MonuseEvent中其他对应坐标的属性

  • MouseEvent.clientX 提供事件发生时的应用客户端区域的水平坐标 (与页面坐标PageX不同,clientX不包含滚动条的距离),所以pageX =clientX+横向滚动的距离
  • MouseEvent.movementX 它提供了当前事件和上一个mousemove事件之间鼠标在水平方向上的移动值,此值可以获取每次鼠标移动的增量,在开发vuedargx没有关注此属性,不然可减少一部分计算代码了。
  • MouseEvent.offsetX 规定了事件对象与目标节点的内填充边(padding edge)在 X 轴方向上的偏移量
  • MouseEvent.screenX 供了鼠标相对于屏幕坐标系的水平偏移量 不包含滚动调距离
  • MouseEvent.x 是 MouseEvent.clientX 属性的别名.

所以,他们之间的关系应该是这样的


offsetX ,因为点击的document,所以此时offsetx=clientx=x,movementX 不好画图,读者就自己联想了。

3.3 自定义事件

用过jQuery的小伙伴,应该多少了解 trigger``triggerHandler方法,触发自定义事件,有了jq的帮助,自定义事件用的是那么得心应手,如丝版顺滑。做为对比,我们先看看jq是如何使用自定义事件的

1 // 添加一个适当的事件监听器
2 $('#foo').on('custom', function(event, param1, param2) {
3 alert(param1 + "\n" + param2);
4 });
5 $('#foo').trigger('custom', ['Custom', 'Event']);

对,就是这么简单,定义,传参一气呵成!
不过用Vue后,这些功能都要用原生的代码实现,业界也越来越强调原生代码呼声也越来越高。或许这句是es标准逐步完善,浏览器逐步兼容新api带来的利好。这里应该向IE6致敬(逃)。
言归正传,标准接口是如何使用自定义事件的呢?于是有找到了MDN https://developer.mozilla.org/zh-CN/docs/Web/API/CustomEvent,找到了demo

// 添加一个适当的事件监听器
obj.addEventListener("custom", function(e) {
console.log(JSON.stringify(e.detail));
})
// 创建并分发事件
var event = new CustomEvent("custom", {"detail":{"Custom":true}});
obj.dispatchEvent(event)

在我看来,定义事件的样子,基本没变,唯一参数传递变得复杂了。总有那么一丢丢不美好。

四、实现

4.1 操作判断

鼠标在目标对象上下左边边缘移动时,鼠标需要显示不同的resize样式,提醒用户当前可操作的类型。基本思路是获取当前对象的在文档对应的left和top值,与上边讲解的MouseEvent中的 pageX、pageY加上可容忍的边沿值做比较,分别分以下几种情况

  1. 左边 left-edge<pageX<left+edge&& top+edge<pageY<top+height-edge
  2. 右边 left+widht-edge<pageX<left+widht+edge&& top+edge<pageY<top+height-edge
  3. 上边 top-edge<pageY<top+edge && left+edge<pageX<left+width-edge
  4. 下边 top+heigth-edge<pageY<top+height+edge && left+edge<pageX<left+width-edge
  5. 左上角 top-edge<pageY<top+edge&&left-edge<pageX<left+edge
  6. 左下角 top+height-edge<pageY<top+height+edge&&left-edge<pageX<left+edge
  7. 右上角 top-edge<pageY<top+edge&&left+width-edge<pageX<left+width+edge
  8. 右下角 top+height-edge<pageY<top+height+edge&&left+width-edge<pageX<left+widht+edge

所以具体代码是这样的


判断当前鼠标是否在拖动对象上就没有那么费劲了,直接在onmousemove事件中通过
e.target.classList.contains(cfg.dragBarClass)判断即可

4.2 调整大小

通过计算得到鼠标移动的deltx和delty值,分别更新width和heigth属性。当前在向左和向上调整大小,还需要调整对一个的left和height属性值

4.3 拖动

拖动,不改变目标对象大小,直接用计算的deltx和delty更新对应的left和top属性即可,如果需要限制移动区域,需要计算父容器对应内边距的坐标

 1 function setConstraint(data) {
 2 if (cfg.dragContainerId) {
 3 let constraintDom = document.querySelector("#" + cfg.dragContainerId);
 4 let constraintRect = constraintDom.getBoundingClientRect();
 5 if (data.left <= 0) data.left = 0;
 6 if (data.top <= 0) data.top = 0;
 7 if (data.top + data.height+data.borderTop+data.borderBottom >= constraintRect.height) data.top = constraintRect.height - data.height-data.borderTop-data.borderBottom;
 8 if (data.left + data.width+data.borderLeft+data.borderRight > constraintRect.width) data.left = constraintRect.width - data.width-data.borderLeft-data.borderRight;
 9 }
10 }

五、总结

虽然功能不大,但要把每一个环节说清楚,感觉还是很费力。真羡慕那些会写书的开发人员,文档能力那是相当的好。写文档真的比不了写代码,不过还是要写,不然别人怎么知道你代码是做啥的。

转载于:https://www.cnblogs.com/yfrs/p/vuedragx.html

一个能拖动,能调整大小,能更新bind值的vue指令-vuedragx相关推荐

  1. 真・WPF 按钮拖动和调整大小

    真・WPF 按钮拖动和调整大小 独立观察员 2020 年 8 月 29 日 手头有个 Winform 程序,是使用动态生成按钮,然后拖动.调整大小,以此来记录一些坐标数据,最后保存坐标数据的. 在数据 ...

  2. android 浮动文字提示,怎么在Android中实现一个自由拖动并显示文字的悬浮框

    怎么在Android中实现一个自由拖动并显示文字的悬浮框 发布时间:2021-01-27 15:34:05 来源:亿速云 阅读:107 作者:Leah 今天就跟大家聊聊有关怎么在Android中实现一 ...

  3. java拖动组件,[小娱乐] 一个能拖动组件、改变组件大小的容器

    [小娱乐] 一个能拖动组件.改变组件大小的容器 /* * JDragpullPane.java * * Created on 2007年3月20日, 上午12:31 */ package javax. ...

  4. python封装一个效率极高的 批量更新、插入合一的工具

    我在写爬虫的时候,经常会获取大量的数据.这个时候大量数据的数据库操作如果不做一定的优化的话,将会耗费大量的时间.通过实践我发现,批量的数据操作将会极大的提高数据库操作的效率.同时,很多时候存在数据如果 ...

  5. vue aplayer 进度条无法拖动_「最近项目小结」使用Vue实现一个简单的鼠标拖拽滚动效果插件...

    演示事例 http://www.longstudy.club/vue-drag-scroll/index.html 最近在做一个新的项目,有个需求是这样的: 简单描述一下,就是鼠标拖动页面,整个页面会 ...

  6. Vue data 中随意更改一个属性,视图都会被更新吗?

    以下内容来自公众号逆锋起笔,关注每日干货及时送达 作者:Rudy24 链接:https://juejin.cn/post/7040733315791323143 面试官:看过 Vue 的源码没? 候选 ...

  7. 【web前端特效源码】使用HTML5+CSS3+JavaScript制作一个可拖动的拼图游戏动画效果~适合初学者~超简单~ |it前端开发

    b站视频演示效果: [web前端特效源码]使用HTML5+CSS3+JavaScript制作一个可拖动的拼图游戏动画效果~适合初学者~超简单~ |前端开发|IT软件 效果图: 完整代码: <!D ...

  8. Android上实现一个简单的天气预报APP(六) 更新界面数据

    学习参考资源:https://www.gitbook.com/book/zhangqx/mini-weather/details 前面我们已经设置好了基本的界面,获取了网络上的天气数据并解析出来了,接 ...

  9. 数据改动,更新视图,类似于vue

    //当数据改变时,更新视图,和vue的有点类似let obj = { name:{ name:'ll' }, age:12,}let arr = [1,2,3];//针对数组的写法//当需要改变原型对 ...

  10. Google今日更新PR值,帆船书会由1升到了3

    帆船书会(http://www.fanchuanbook.com)是我利用业余时间做的一个读书网站, 08年8月份上线的,一直在更新书籍,也在慢慢的弄程序,改进用户体验. 上次google更新pr值时 ...

最新文章

  1. 2021年4月22日 阿里供应链Java开发实习面试(三面)(含总结)
  2. python做logistic回归_用Python做Logistic回归
  3. 媒体转码升级为媒体处理
  4. linux 打开关闭文件,Linux系统编程-文件打开关闭
  5. 视频专辑:Hibernate 视频
  6. 面试中关于Redis的问题看这篇就够了
  7. 【学习笔记】计算机导论之计算机软件
  8. 使用python实现栈和队列
  9. 全文搜索引擎 Elasticsearch 入门(ik,kibana,x-pack)
  10. 网络编程聊天室----服务器端
  11. UnicodeEncodeError: #39;ascii#39; codec can#39;t encode character u#39;\u5929#39; in position 2...
  12. 牛腩新闻发布系统错误总结
  13. ABB伺服驱动调试(四)
  14. 带你揭秘网络工程师群体!
  15. 《Git与Github使用笔记》第8章 github常见操作和常见错误
  16. 电商与硬件——从购买电脑的角度学计算机硬件基础
  17. php xirr,一个傻瓜式的计算方法,教你算出投资的真实收益率
  18. 微星性能测试软件,MSI Kombustor
  19. xt.loadOnStartup web应用程序[]中的Servlet[springmvc]引发了load()
  20. 同网络的计算机能共享音箱吗,2019年PC“老爷机”局域网内DLNA共享音乐到小度智能音箱全记录...

热门文章

  1. oracle创建用户、创建表空间、授权、建表
  2. drupal.behavior 和 document.ready 没有直接的关系
  3. 最值得一看的几条简单的谷歌 Google 搜索技巧,瞬间提升你的网络搜索能力
  4. Mac OS X从10.7升级到Mountain Lion OS X10.8
  5. [我的常识]动物庄园里说鼻环,到底为啥要穿鼻环呢
  6. 成为java高手的八大条件
  7. React中state与props介绍与比较
  8. angulrar知识点整理
  9. 点聚-weboffice 6.0 (一)
  10. 新安装 Ubuntu 12.10 需要做的 10 件事(转)