vue实现拖拽的组件

<1>

安装

通过NPM安装

$ npm install awe-dnd --save

插件应用

在main.js中,通过Vue.use导入插件

import VueDND from 'awe-dnd'

Vue.use(VueDND)

在你的vue文件中这样引用



vue2.0的使用方式

{{color.text}}

vue1.0的使用方式

{{color.text}}

添加事件

{{color.text}}
export default {
  mounted () {
    this.$dragging.$on('dragged', ({ value }) => {
      console.log(value.item)
      console.log(value.list)
      console.log(value.otherData)
    })
    this.$dragging.$on('dragend', () => {
        
    })
  }
}

组件参数

名称类型默认值说明

item Object - 每一个可拖拽的对象
list Array - 可拖拽对象的数组
group String - 这是一个dragging list的unique key

 

<2>vue 组件排列顺序

安装

npm install awe-dnd --save
  •  

main.js

import VueDND from 'awe-dnd'

Vue.use(VueDND)
  •  

sortable.vue

  •  

  排序完后的操作挺重要的,因为我们一般排序完要重新提交排序后的数据给后台保存,以便下一次安装我们所需要的顺序显示,这里的list就可以帮我们做到这一点,但是我们需要给数据添加一个uniqueId标志。然后在排序完后或者列表对应的顺序和uniqueId提交给后台,我也不知道我说的你们能理解吗,反正你们也可以打印出来看看。

效果
vue实现拖拽的组件_第1张图片

<3>

https://blog.csdn.net/u011384023/article/details/79762299

 

<4>

一个基于 Sortable.js 的vue拖拽插件 支持触屏操作 自动适应 draggable组件的v-model属性实现双向绑定。 如果要多个盒子互相拖拽,需定义options,将其group属性定义为同一个值即可 源码如下:

vue实现拖拽的组件_第2张图片 

一个基于Sortable.js的vue拖拽插件
支持触屏操作
自动适应




draggable组件的v-model属性实现双向绑定。

如果要多个盒子互相拖拽,需定义options,将其group属性定义为同一个值即可

源码如下:
 

Document

 

 

{{element}}

{{fruit}}



 

{{element}}

{{girl}}

 

<5>https://blog.csdn.net/qq_40882724/article/details/80798135

:翻看vue文档发现可以注册全局指令,用于DOM元素的底层处理,这个挺靠谱。

Vue.directive( 指令名,{ 钩子函数 } )

vue实现拖拽的组件_第3张图片

3.思路:很简单:首先记录整个对话框距离文档边界的左边距和上边距(当然你监听右边距也oK的,但是别监听下边距,因为我们一般是设置上边距,饿了么也是如此。正如我们调整高度时,会说往下拉一点,或者往上去一点)。鼠标按下的时候监听mousedown事件,记录鼠标距离对话框边界的距离(左边距LEFT,上边距TOP).然后监听document的mousemove事件,因为我们不可能确保我们的鼠标一直都在框中拖拽,因为我们速度有慢有快,在mousemove中保证鼠标与对话框的位置跟mousedown时一致。鼠标mouseup时移除mousemove和mouseup的监听,下次对话框打开时再把它的位置还原如初

4.思考过程:

 

  1. 使用哪些钩子?  因为我们要记录初始位置,并保存记录,采用inserted钩子,可以保证我们能正确地访问到相关样式属性,在componentUpdated里当对话框打开时再把位置还原到拖拽之前的位置。
  2. computedStyle or element.style?因为有的样式写在行内有的样式写在样式表里,思考后决定统一使用getComputedstyle,然后发现有些是空字符"",有些是"auto"我嘞个去。这怎么办?问题到这里已经很清晰了,那就是根据样式来获取距离不靠谱。
  3. 计算获取marginLeft,marginTop,我们通过html的宽度与对话框的宽度之差获取对话框左边距
  4. 再通过鼠标事件里的event.clientX、event.clientY 获取鼠标到对话框的距离。并处理。
  5. componentUpdated里还原位置。
 
  1. let marginLeft = (compotedStyle(document.firstElementChild).width -computedStyle(dialogEle).width)/2

  2. //此处注意把值转换为数字格式

5.贴上代码:

 
  1. import Vue from 'vue'

  2. let LEFT;

  3. let TOP;

  4. //指令的传参形式为

  5. Vue.directive('dialogdrag',{

  6. inserted(el,binding){

  7. let container = el.querySelector(binding.value.container);

  8. let target = el.querySelector(binding.value.target);

  9.  
  10.  
  11. let temContainerWidth = getComputedStyle(container).width;

  12. let temHtmlWidth = getComputedStyle(document.firstElementChild).width;

  13. if(temContainerWidth.indexOf('%') != -1){

  14. //百分值

  15. LEFT = (

  16. parseFloat(temHtmlWidth) -

  17. parseFloat(temHtmlWidth) * temContainerWidth.substring(0,temContainerWidth.length-1)/100

  18. )/2;

  19. }else if(temContainerWidth.indexOf('px') != -1){

  20. //像素值

  21. LEFT = (

  22. parseFloat(temHtmlWidth) -

  23. parseFloat(temContainerWidth)

  24. )/2;

  25. }else{

  26. //其他值

  27. throw ('对话框容器宽度只能为像素或百分比!')

  28. }

  29. console.log(temContainerWidth);

  30. console.log(temHtmlWidth);

  31. //

  32. let temMarginTop = getComputedStyle(container).marginTop;

  33. if(temMarginTop && temMarginTop.indexOf('px') != -1){

  34. //不为空并且以像素为单位

  35. TOP = parseFloat(temMarginTop);

  36. }else{

  37. throw ('请设置对话框容器上边距margin-top并以像素为单位!')

  38. }

  39. console.log(LEFT)

  40. //删除对话容器的行内样式(marginleft,margintop,marginbottom,marginrigth);

  41. delete container.style.marginTop;

  42. delete container.style.marginLeft;

  43. delete container.style.marginRight;

  44. delete container.style.marginBottom;

  45. delete container.style.margin;

  46. //赋值给marginTop;marginLeft;

  47. container.style.marginTop = TOP+'px';

  48. container.style.marginLeft = LEFT+'px';

  49.  
  50. //事件监听

  51. target.addEventListener('mousedown',function(event){

  52. //获取鼠标距离对话框容器的左上边距

  53. let leftValue = event.clientX - parseFloat(getComputedStyle(container).marginLeft);

  54. let topValue = event.clientY - parseFloat(getComputedStyle(container).marginTop);

  55. document.addEventListener('mousemove',moveFn,true)

  56. document.addEventListener('mouseup',upFn,true)

  57. function moveFn(event){

  58. console.log('还在移动')

  59. target.style.cursor = 'move';

  60. container.style.marginLeft = (event.clientX-leftValue)+'px';

  61. container.style.marginTop = (event.clientY-topValue)+'px';

  62.  
  63. }

  64. function upFn(event){

  65. target.style.cursor = 'default';

  66. document.removeEventListener('mousemove',moveFn,true);

  67. //document.removeEventListener('mouseup',upFn);

  68. }

  69. })

  70. },

  71. componentUpdated(el,binding){

  72. if(binding.value.dialogVisible){

  73. //打开时还原对话框位置

  74. el.querySelector(binding.value.container).style.marginTop = TOP+'px';

  75.  
  76. el.querySelector(binding.value.container).style.marginLeft = LEFT+'px';

  77.  
  78. }

  79. }

  80. })

 

你可能感兴趣的:(前端环境)