There are many pulling wheels on the Internet, but there are always some demands that the wheels can't meet. When the use of wheels can not meet their own needs, the use of H5 native dragging method has the following advantages:
- api is rich and flexible to implement drag-and-drop requirements
- It avoids the inconvenience of bug modification of wheel itself.
In order to make myself deeply understand the api, I simplified and implemented a drag-and-drop example in the vue project according to the requirement, which is also for your reference.
The requirements are as follows:
- The left area field does not support sorting, but it can be dragged to the right to hierarchize, dimension, and contrast areas.
- The left area field can also be dragged onto the first field that the dimension area has dragged, creating a hierarchical relationship that is displayed in the hierarchical area.
- Fields dragged to dimensions and contrast areas support drag-and-drop exchanges, but cannot be dragged after the first field of a dimension generates a hierarchical relationship.
- Fields in hierarchical areas do not support drag sorting
The code is as follows:
//Part HTML <div style="margin-top: 100px;"> <div class="drag-container"> <p v-for="item in list" draggable="true" @dragstart="dragstart($event,item,'list')" @dragend="dragend($event,item)" >{{item.name}}</p> </div> <div class="drop-container"> <p>Layered</p> <div class="drop-area" v-if="showLayer" @drop="drop($event,'layer')" @dragenter="dragenter" @dragover="dragover" > <p v-for="(item,index) in layer"> <span draggable="true" @dragstart="dragstart($event,item,'layer',index)" >{{item.name}}</span> <b v-if="index!=layer.length-1">-></b> </p> </div> <p>dimension</p> <div class="drop-area" @drop="drop($event,'dimensions')" @dragover="dragover"> <span v-for="(item,index) in dimensions" @drop="dropToItem($event,item)" @dragover.prevent draggable="true" @dragstart="dragstart($event,item,'dimensions',index)" >{{item.name}}</span> </div> <p>Contrast</p> <div class="drop-area" @drop="drop($event,'contrasts')" @dragover="dragover"> <span v-for="(item,index) in contrasts" @dragover.prevent draggable="true" @dragstart="dragstart($event,item,'contrasts',index)" >{{item.name}}</span> </div> </div> </div><template> <div style="margin-top: 100px;"> <div class="drag-container"> <p v-for="item in list" draggable="true" @dragstart="dragstart($event,item,'list')" @dragend="dragend($event,item)" >{{item.name}}</p> </div> <div class="drop-container"> <p>Layered</p> <div class="drop-area" v-if="showLayer" @drop="drop($event,'layer')" @dragenter="dragenter" @dragover="dragover" > <p v-for="(item,index) in layer"> <span draggable="true" @dragstart="dragstart($event,item,'layer',index)" >{{item.name}}</span> <b v-if="index!=layer.length-1">-></b> </p> </div> <p>dimension</p> <div class="drop-area" @drop="drop($event,'dimensions')" @dragover="dragover"> <span v-for="(item,index) in dimensions" @drop="dropToItem($event,item)" @dragover.prevent draggable="true" @dragstart="dragstart($event,item,'dimensions',index)" >{{item.name}}</span> </div> <p>Contrast</p> <div class="drop-area" @drop="drop($event,'contrasts')" @dragover="dragover"> <span v-for="(item,index) in contrasts" @dragover.prevent draggable="true" @dragstart="dragstart($event,item,'contrasts',index)" >{{item.name}}</span> </div> </div> </div>
//Part js export default { name: "drag", data(){ return { dragItem:{},//Drag fields dragFrom:'',//Where does the drag start? dragIndex:'',//Index of dragged fields in an array dropIndex:'',//Index of fields put into place showLayer:false,//Whether to display layering isDropToItem:false,//Whether to drag to the dimension field for hierarchical operation layer:[], dimensions:[], contrasts:[], list:[ { id:1, name:'Full name' },{ id:2, name:'Gender' },{ id:3, name:'Age' },{ id:4, name:'Fraction' }] } }, methods:{ //Drag and drop start dragstart(event,item,frm,index){ console.log('------dragstart------') if(this.BrowserType().name == "FF"){ // Compatible with Firefox Browser, Firefox drag must carry data console.log(event.dataTransfer.setData("imgInfo", event.target.id)); } this.dragItem = item; this.dragFrom = frm; if(!isNaN(index)){ this.dragIndex = index; } }, //Enter the drag area, trigger once when entering dragenter(event){ console.log('------dragenter------') }, //Triggered multiple times after entering the drag area dragover(event){ event.preventDefault(); var target = event.target; this.dropIndex = this.indexFn(target) var nodeName = target.nodeName; if(nodeName!='SPAN'){ this.dropIndex = -1; } }, //Release the mouse to trigger after dragging drop(event,target){ console.log('------drop------') var dragFrom = this.dragFrom; var dragItem = this.dragItem; var dragIndex = this.dragIndex; var dropIndex = this.dropIndex; if(this.isDropToItem){ return; } if(this.dragFrom == 'layer'){ this.layer.splice(dragIndex,1); }else if(this.dragFrom == 'dimensions'){ this.dimensions.splice(dragIndex,1); }else if(this.dragFrom == 'contrasts'){ this.contrasts.splice(dragIndex,1); } if(dragFrom == target && dropIndex>-1){ var targetArr = this[target]; targetArr.splice(dropIndex,0,dragItem); return; } if(target == 'layer'){ this.layer.push(dragItem); }else if(target == 'dimensions'){ this.dimensions.push(dragItem); }else if(target == 'contrasts'){ this.contrasts.push(dragItem); } }, //Triggered when dragged to the first field of the dimension dropToItem(event,item){ console.log('------dropToItem------') if(this.dragFrom != 'list'){ this.isDropToItem = false return; }else { this.isDropToItem = true } if(this.showLayer){ this.layer.push(this.dragItem); }else{ this.showLayer = true; this.layer.push(item); this.layer.push(this.dragItem); } }, //Triggered after the drag, whether or not the drag succeeded dragend(event,item){ console.log('------dragend------') this.isDropToItem = false }, //Determine the drag field so that it is used for sorting indexFn(el) { var index = 0; if (!el || !el.parentNode) { return -1; } while (el && (el = el.previousElementSibling)) { index++; } return index; }, //Browser Judgment BrowserType(){ var userAgent = navigator.userAgent; //Get the browser's userAgent string var isOpera = userAgent.indexOf("Opera") > -1; //Judging Opera Browser var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1 && !isOpera; //Judging whether IE browser or not var isEdge = userAgent.indexOf("Windows NT 6.1; Trident/7.0;") > -1 && !isIE; //Edge Browser for IE var isFF = userAgent.indexOf("Firefox") > -1; //Determine whether Firefox browsers are available var isSafari = userAgent.indexOf("Safari") > -1 && userAgent.indexOf("Chrome") == -1; //Determine whether Safari browser is available or not var isChrome = userAgent.indexOf("Chrome") > -1 && userAgent.indexOf("Safari") > -1; //Judging Chrome Browser if (isIE) { var reIE = new RegExp("MSIE (\\d+\\.\\d+);"); reIE.test(userAgent); var fIEVersion = parseFloat(RegExp["$1"]); return {name:"IE",num: fIEVersion}; }//isIE end if (isFF) { return {name:"FF",num: "FF"};} if (isOpera) { return {name:"Opera",num: "Opera"};} if (isSafari) { return {name:"Safari",num: "Safari"};} if (isChrome) { return {name:"Chrome",num: "Chrome"};} if (isEdge) { return {name:"Edge",num: "Edge"};} } } }
/* css Part */ .drag-container{ width: 100px;height: 500px;float: left; background-color: #BAB5F5; p{ line-height: 40px; text-align: center; cursor: pointer; } } .drop-container{ margin-left: 120px; float: left;height: 500px; width: 600px; p{ color: #fff;line-height: 40px; } .drop-area{ height: 80px; width: 600px; background-color: #4c72ff;padding: 10px; p{ display: inline-block; margin: 0; } span{ display: inline-block;min-width: 50px;line-height: 40px;margin-right: 5px;background-color: #5a3e99;text-align: center;cursor: pointer; } } }