这周公司要求我去调研一下腾讯问卷系统的编辑问卷实现的功能
对于一个前端er 来说,去研究别人的前端交互是很有热情的。当中除了一些简单的css 样式在短时间内是可以模仿出来,除了拖拽改变序列让我沉思了比较久的时间,其他都很快就弄通透了。
那么就开始吧
首先,我使用的JQuery+Vue 来完成的
第一是我需要一个能帮我完成数据绑定的框架,第二个是我需要对DOM进行大量操作才能完成拖拽改变序列这一工作。
既然要实现拖动,并且要有一个好看的动画效果,首先我就把 drag事件给否认了。
我心目中最合适的就是 mousedown , mousemove, mouseup了
我在每个div 中 都绑定了一个mousedown 事件,并且当mousedown触发时 随之绑定 document 的 mousemove 与 mouseup 事件, 只有当用户 触发mouseup 才注销掉 mousemove 与 mouseup 的 事件
我的处理方式是将需要遍历的数组 做一个备份, 每当我们拖拽(mousedown&mousemove)某一个元素时,就深拷贝一个备份数组,并将当中的对应拖拽元素删去,然后根据拖动的高度,添加到对应的index 中,并将排序好的数组赋值给遍历数组,完成预览效果, 当用户触发mouseup时 将遍历数组赋值给拷贝数组,就完成了拖拽排序啦!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>drag</title>
<script src="./vue.js"></script>
<script src="jquery.js"></script>
<style>
* {
padding: 0;
margin: 0;
user-select: none;
}
.item:nth-child(even) {
background: #EFEFEF;
}
.item:nth-child(odd) {
background: #e0e0e0;
}
.item {
width: 200px;
height: 50px;
padding: 5px;
}
.item-mask {
position: absolute;
left: 0;
width: 200px;
height: 50px;
padding: 5px;
background: yellow;
}
</style>
</head>
<body>
<div id="app">
<div class="item" v-for="(item,index) in message" v-show="index!=0" @mousedown="down($event,index)">
{{item}}
</div>
<div class="item-mask" :style={top:curTop+'px'} v-if="curItem!=''" v-show="show">{{curItem}}</div>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
message: ['', 1, 2, 3, 4, 5, 6],
bakmessage: ['', 1, 2, 3, 4, 5, 6],
show: false,
curItem: '',
heightArr: [],
curTop: 0
},
created() {
this.initHeight();
},
methods: {
down(evt, idx) {
let me = this;
this.curItem = this.message[idx];
this.curTop = $('.item').eq(idx).position().top;
this.show = true;
var offsetY = evt.layerY;
$(document).on('mousemove', function (e) {
me.move(e, idx, offsetY)
});
$(document).on('mouseup', function (e) {
me.up(e)
});
},
move(e, index, offsetY) {
var bak = deepCopy(this.bakmessage);
let me = this;
let relY = e.clientY - offsetY + 60 * (index-1);
this.curTop = relY;
console.log(relY)
this.heightArr.map(function (item, i, arr) {
if (me.curTop > item && me.curTop < arr[i + 1]) {
bak.splice(index, 1);
bak.splice(i + 1, 0, me.curItem)
me.message = bak;
}
});
},
up(e) {
this.show = false;
this.bakmessage = this.message;
$(document).unbind('mousemove')
},
initHeight() {
let arr = [];
this.$nextTick(function () {
this.message.map(function (item, index) {
var top = $('.item').eq(index).position().top;
arr.push(top + 60)
});
this.heightArr = arr;
this.heightArr.unshift(-30)
this.heightArr.push(390)
})
}
}
})
function isArr(obj) { // 检验该对象是不是数组
return Object.prototype.toString.call(obj) === '[object Array]'
}
function deepCopy(obj) {
var newObj = isArr(obj) === true ? [] : {};
for (let item in obj) {
if (typeof obj[item] === 'object') {
newObj[item] = deepCopy(obj[item])
} else {
newObj[item] = obj[item]
}
}
return newObj
}
</script>
</html>
代码复制了,就可以看,这个是我个人做的一个demo,可以参考着使用