先上一張效果圖,而後再上代碼(因爲只作效果,未作數據相關的處理:實際處理數據時不修改 dom 元素,只是利用 dom 元素傳遞數據,而後需改數據,靠數據驅動效果)javascript
<div :id="index+'_morning'" style="min-height: 20px;" @drop='drop($event)' @dragover='allowDrop($event)'> <li style="padding:0 0 5px 0"> <span class="type-icon time">上</span>上午(morning) </li> <template v-if="item.morning !== undefined"> <template v-for="(itemSon,idIdx) in item.morning"> <li class="item ui-sortable-handle" :id="index+'_morning_'+idIdx" draggable='true' @dragstart='drag($event)' @drop='drop($event)' @dragover='allowDrop($event)'> <span class="destination-name"> <em class="ball ball-red">{{itemSon.node_sort}}</em> <a href="javascript:;" class="item-name">{{itemSon.name}}</a> <NodeSetMore @click="onEventPoi(itemSon)" :poi="itemSon" v-on:poiOperate="onPoiOperate"></NodeSetMore> <DisplayIcon :poi="itemSon"></DisplayIcon> </span> </li> </template> </template> </div>
methods: { // 拖拽相關 drag:function(event){ console.log('拖動事件', event) this.dom = event.currentTarget }, drop:function(event){ event.preventDefault(); // 組織事件的傳播(防止冒泡,節點向節點容器冒泡,由於都監聽了此事件) event.cancelBubble = true; console.log('源對比', event.target, event.currentTarget) console.log('目標id', event.currentTarget.id) // 爲event.currentTarget(點擊事件自己) // 分割id 2_morning格式爲容器;2_morning_0爲容器下的節點: const idPath = event.currentTarget.id.split('_'); if (idPath.length === 2) { event.currentTarget.appendChild(this.dom); } else if(idPath.length === 3) { // 獲取當前排序第幾,而後插在這個元素以後 event.currentTarget.parentNode.appendChild(this.dom); // 從新改變順序data中的數組順序 this.againSort() } else { console.log("暫不處理", event.target) } //// 數據處理階段,若是是節點容器,直接插在最前面,若是是節點,則放在這個節點後面 // // 不改變dom節點,直接改變數據 // this.tripList['1']['morning'].splice(0, 1); // this.againSort() }, allowDrop:function(event){ event.preventDefault(); // 組織事件的傳播 event.cancelBubble = true; } }
主要關注點在於 event.target 和 event.currentTarget 的理解,一個是事件觸發時點擊的元素(如:span),一個是事件觸發時點擊綁定事件的元素(如:li @drop)java