<1>
安装
通过NPM安装
$ npm install awe-dnd --save
插件应用
在main.js中,通过Vue.use导入插件
import VueDND from 'awe-dnd'
Vue.use(VueDND)
在你的vue文件中这样引用
<script>
export default {
data () {
return {
colors: [{
text: "Aquamarine"
}, {
text: "Hotpink"
}, {
text: "Gold"
}, {
text: "Crimson"
}, {
text: "Blueviolet"
}, {
text: "Lightblue"
}, {
text: "Cornflowerblue"
}, {
text: "Skyblue"
}, {
text: "Burlywood"
}]
}
}
}
</script>
<template>
<div class="color-list">
<div
class="color-item"
v-for="color in colors" v-dragging="{ item: color, list: colors, group: 'color' }"
:key="color.text"
>{{color.text}}</div>
</div>
</template>
vue2.0的使用方式
<div class="color-list">
<div
class="color-item"
v-for="color in colors" v-dragging="{ item: color, list: colors, group: 'color' }"
:key="color.text"
>{{color.text}}</div>
</div>
vue1.0的使用方式
<div class="color-list">
<div
class="color-item"
v-for="color in colors" v-dragging="{ item: color, list: colors, group: 'color', key: color.text }"
track-by="text"
>{{color.text}}</div>
</div>
添加事件
<div class="color-list">
<div
class="color-item"
v-for="color in colors" v-dragging="{ item: color, list: colors, group: 'color', otherData: otherData }"
:key="color.text"
>{{color.text}}</div>
</div>
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提交给后台,我也不知道我说的你们能理解吗,反正你们也可以打印出来看看。
效果
<3>
https://blog.csdn.net/u011384023/article/details/79762299
<4>
一个基于 Sortable.js 的vue拖拽插件 支持触屏操作 自动适应 draggable组件的v-model属性实现双向绑定。 如果要多个盒子互相拖拽,需定义options,将其group属性定义为同一个值即可 源码如下:
一个基于Sortable.js的vue拖拽插件
支持触屏操作
自动适应
draggable组件的v-model属性实现双向绑定。
如果要多个盒子互相拖拽,需定义options,将其group属性定义为同一个值即可
源码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="http://cdnjs.cloudflare.com/ajax/libs/vue/2.5.2/vue.min.js"></script>
<script src="http://cdn.jsdelivr.net/npm/sortablejs@1.7.0/Sortable.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/Vue.Draggable/2.15.0/vuedraggable.min.js"></script>
</head>
<body>
<div id="tuozhuai_view">
<!-- -->
<draggable v-model="fruit" :options="{group:'people'}">
<div v-for="element in fruit">{{element}}</div>
</draggable>
{{fruit}}
<br>
<br>
<draggable v-model="girl" :options="{group:'people'}">
<div v-for="element in girl">{{element}}</div>
</draggable>
{{girl}}
</div>
<script type="text/javascript">
new Vue({
el:'#tuozhuai_view',
data:{
fruit:['apple','banana','orage'],
girl:['linzhil','cjk','bdyjy'],
}
})
</script>
</body>
</html>
<5>https://blog.csdn.net/qq_40882724/article/details/80798135
:翻看vue文档发现可以注册全局指令,用于DOM元素的底层处理,这个挺靠谱。
Vue.directive( 指令名,{ 钩子函数 } )
3.思路:很简单:首先记录整个对话框距离文档边界的左边距和上边距(当然你监听右边距也oK的,但是别监听下边距,因为我们一般是设置上边距,饿了么也是如此。正如我们调整高度时,会说往下拉一点,或者往上去一点)。鼠标按下的时候监听mousedown事件,记录鼠标距离对话框边界的距离(左边距LEFT,上边距TOP).然后监听document的mousemove事件,因为我们不可能确保我们的鼠标一直都在框中拖拽,因为我们速度有慢有快,在mousemove中保证鼠标与对话框的位置跟mousedown时一致。鼠标mouseup时移除mousemove和mouseup的监听,下次对话框打开时再把它的位置还原如初。
4.思考过程:
- 使用哪些钩子? 因为我们要记录初始位置,并保存记录,采用inserted钩子,可以保证我们能正确地访问到相关样式属性,在componentUpdated里当对话框打开时再把位置还原到拖拽之前的位置。
- computedStyle or element.style?因为有的样式写在行内有的样式写在样式表里,思考后决定统一使用getComputedstyle,然后发现有些是空字符"",有些是"auto"我嘞个去。这怎么办?问题到这里已经很清晰了,那就是根据样式来获取距离不靠谱。
- 计算获取marginLeft,marginTop,我们通过html的宽度与对话框的宽度之差获取对话框左边距
- 再通过鼠标事件里的event.clientX、event.clientY 获取鼠标到对话框的距离。并处理。
- componentUpdated里还原位置。
let marginLeft = (compotedStyle(document.firstElementChild).width -computedStyle(dialogEle).width)/2
//此处注意把值转换为数字格式
5.贴上代码:
-
import Vue from 'vue'
-
let LEFT;
-
let TOP;
-
//指令的传参形式为<dialogo v-dialogdrag=" { target:'selector',container:'.box',dialogVisible:"传入对话框的visible变量" } "></dialog>
-
Vue.directive('dialogdrag',{
-
inserted(el,binding){
-
let container = el.querySelector(binding.value.container);
-
let target = el.querySelector(binding.value.target);
-
let temContainerWidth = getComputedStyle(container).width;
-
let temHtmlWidth = getComputedStyle(document.firstElementChild).width;
-
if(temContainerWidth.indexOf('%') != -1){
-
//百分值
-
LEFT = (
-
parseFloat(temHtmlWidth) -
-
parseFloat(temHtmlWidth) * temContainerWidth.substring(0,temContainerWidth.length-1)/100
-
)/2;
-
}else if(temContainerWidth.indexOf('px') != -1){
-
//像素值
-
LEFT = (
-
parseFloat(temHtmlWidth) -
-
parseFloat(temContainerWidth)
-
)/2;
-
}else{
-
//其他值
-
throw ('对话框容器宽度只能为像素或百分比!')
-
}
-
console.log(temContainerWidth);
-
console.log(temHtmlWidth);
-
//
-
let temMarginTop = getComputedStyle(container).marginTop;
-
if(temMarginTop && temMarginTop.indexOf('px') != -1){
-
//不为空并且以像素为单位
-
TOP = parseFloat(temMarginTop);
-
}else{
-
throw ('请设置对话框容器上边距margin-top并以像素为单位!')
-
}
-
console.log(LEFT)
-
//删除对话容器的行内样式(marginleft,margintop,marginbottom,marginrigth);
-
delete container.style.marginTop;
-
delete container.style.marginLeft;
-
delete container.style.marginRight;
-
delete container.style.marginBottom;
-
delete container.style.margin;
-
//赋值给marginTop;marginLeft;
-
container.style.marginTop = TOP+'px';
-
container.style.marginLeft = LEFT+'px';
-
//事件监听
-
target.addEventListener('mousedown',function(event){
-
//获取鼠标距离对话框容器的左上边距
-
let leftValue = event.clientX - parseFloat(getComputedStyle(container).marginLeft);
-
let topValue = event.clientY - parseFloat(getComputedStyle(container).marginTop);
-
document.addEventListener('mousemove',moveFn,true)
-
document.addEventListener('mouseup',upFn,true)
-
function moveFn(event){
-
console.log('还在移动')
-
target.style.cursor = 'move';
-
container.style.marginLeft = (event.clientX-leftValue)+'px';
-
container.style.marginTop = (event.clientY-topValue)+'px';
-
}
-
function upFn(event){
-
target.style.cursor = 'default';
-
document.removeEventListener('mousemove',moveFn,true);
-
//document.removeEventListener('mouseup',upFn);
-
}
-
})
-
},
-
componentUpdated(el,binding){
-
if(binding.value.dialogVisible){
-
//打开时还原对话框位置
-
el.querySelector(binding.value.container).style.marginTop = TOP+'px';
-
el.querySelector(binding.value.container).style.marginLeft = LEFT+'px';
-
}
-
}
-
})