Background:
Received a new demand, request to use VUE, mainly drag to achieve the layout, the key points are: Individual components drag, drag more than one line the inside of the column component, a single component can be dragged into more than a line in the column, a single component of drag good implementation, the key is to drag the one component to another similar to the form, and in some cases also need to limit the drag only in horizontal direction, to collect data, experiment, finally get out.
In principle, there are two main categories:
- HTML5’s own drag-and-drop API, available libraries are: vue.draggable
- Use JS to monitor mouse movement position, available library is: jquery UI
- Use point-event: None (more on that below)
Their respective shortcomings
Disadvantages of H5 dragging: you can’t limit dragging to horizontal or vertical directions.
Disadvantages of using native JS: a lot of DOM manipulation, complex code (jquery UI package is better, can be used directly)
Draggable (vue. Draggable); draggable (vue. Draggable); drag (vue. Draggable);
Looking for solutions
The first attempt:
<! DOCTYPE HTML > < HTML > <head> <title> Vue with native JS implementation drag </title> <script SRC ="https://cdn.bootcss.com/vue/2.4.2/vue.min.js"></script>
</head>
<body>
<div id="app">
<div class="ctn ctn1">
<div class="sub sub1" v-for="(site, index) in list1">
<div class="dragCtn fixed" :style="{ left: X+'px', top: Y+'px'}"
@mousedown="mousedown(site, $event)"
@mousemove.prevent='mousemove(site, $event)'
@mouseup='mouseup(site, $event)'> drag me </div> </div> <div class="ctn ctn2">
<div class="sub sub2" v-for="(site, index) in list2"
@mouseenter='mouseenter(site, $event)'>
<div class="dragCtn">
{{ index }} : {{ site.name }}
</div>
</div>
</div>
</div>
<script>
new Vue({
el: '#app',
data: {
list1: [{name:1, index:0}],
list2: [{name:'a', index:0}, {name:'b', index:1}, {name:'c', index: 2}, {name:'d', index: 3}],
vm:' ',
sb_bkx: 0,
sb_bky: 0,
is_moving: false,
X: 0,
Y: 0
},
methods: {
mousedown: function (site, event) {
var startx=event.x;
var starty=event.y;
this.sb_bkx=startx - event.target.offsetLeft;
this.sb_bky=starty - event.target.offsetTop;
this.is_moving = true;
},
mousemove: function (site, event) {
var endx=event.x - this.sb_bkx;
var endy=event.y - this.sb_bky;
var _this = this
if(this.is_moving){
this.X = endx;
this.Y = endy;
}
},
mouseup: function (e) {
this.is_moving = false;
},
mouseenter: function (){
console.log('Mouse in')
}
}
})
</script>
<style>
.ctn{
line-height: 50px;
cursor: pointer;
font-size: 20px;
text-align: center;
float: left;
}
.sub:hover{
background: #e6dcdc;
color: white;
width: 100px;
}
.ctn1{
border: 1px solid green;
width: 100px;
}
.ctn2{
border: 1px solid black;
width: 100px;
margin-left: 50px;
}
.fixed{
width: 100px;
position: fixed;
background: red;
left: 0;
top: 0;
cursor: move;
}
</style>
</body>
</html>
Copy the code
In this way, the basic drag is achieved, but when dragging, you can not touch the mouseenter event, and the mouse must drag slowly, move a little faster, drag div can not keep up with, this point is still confused, hope you guys Pointers. Then on the Internet to find a lot of information, class library, but not fully meet my needs, so ready to write their own;
Add a mouseDown event to the component, then listen for the mouse position while mousemove, and assign a value to the component to implement the drag. However, when the component drags into another element, it cannot listen for the MouseEnter event. The none attribute is used to remove the original mouse event and trigger the mouerEnter event of other components.
www.zhangxinxu.com/wordpress/2…
Since dragging is written in native JS, the ability to limit dragging to horizontal, plus the ability to trigger the MouseEnter event, is exactly what I need.
The pseudocode is as follows:
mousedown: function (event, site) {
document.onmousemove=function(ev) {// Add the point-event: None attribute to the element when moving... } document.onmouseup=function(ev) {// Remove the point-event attribute when up... }}Copy the code
The point Event: None attribute is compatible with IE11. The point Event attribute is compatible with IE11.
The old version of drag is based on jquery UI, so go to see the source code of jquery UI, see how it is implemented.
Jquery UI drag implementation principle
If you are not familiar with the dragging method of jquery UI, take a look here
Take a look at this code:
$(function() {$("#draggable" ).draggable();
$( "#droppable" ).droppable({
drop: function( event, ui ) {
$( this ).html( "Dropped!"); }}); });Copy the code
$(“#droppable”); $(“#droppable”); $(“#droppable”) : $(“#droppable”) : $(“#droppable”) : $(“#droppable”)
Along with this idea, I did an experiment to meet my own needs.
The demo results are as follows:
The code address: https://github.com/YalongYan/vue-drag-layout
There should be a better way to implement drag layout, welcome to propose a better way to implement.