可拖动排序的列表 drag-list,这个比较简单易懂,拿例子直接运行看效果就好了。
组件代码:
1 <template> 2 <ul class="list" ref="parentNode" @dragstart="onDragStart" @dragover="onDragOver" @dragend="onDragEnd"> 3 <li class="list-item" v-for="(item, index) in dataProvider" :key="item[valueKey]" :id="item[valueKey]" 4 :draggable="draggable"> 5 <slot :item="item" :index="index"> 6 <div>{{ item }}</div> 7 </slot> 8 </li> 9 </ul> 10 </template> 11 12 <script> 13 const _LI_ = 'LI'; 14 15 export default { 16 name: 'LiloDragList', 17 props: { 18 dataProvider: { 19 type: Array, 20 default () { 21 return {} 22 } 23 }, 24 draggable: { 25 type: Boolean, 26 default: true 27 }, 28 valueKey: { 29 type: String, 30 default: 'id' 31 } 32 }, 33 data() { 34 return { 35 draging: null, 36 target: null 37 }; 38 }, 39 mounted() { 40 document.body.ondrop = event => { 41 event.preventDefault(); 42 event.stopPropagation(); 43 }; 44 }, 45 methods: { 46 onDragStart(event) { 47 // console.log('drag start'); 48 this.draging = event.target; 49 }, 50 onDragOver(event) { 51 // console.log(event.target.nodeName); 52 this.target = event.target; 53 let targetTop = event.target.getBoundingClientRect().top; 54 let dragingTop = this.draging.getBoundingClientRect().top; 55 if (this.target.nodeName === _LI_ && this.target !== this.draging) { 56 if (this.target) { 57 if (this.target.animated) { 58 return; 59 } 60 } 61 62 if (this._index(this.draging) < this._index(this.target)) { 63 this.target.parentNode.insertBefore(this.draging, this.target.nextSibling); 64 } else { 65 this.target.parentNode.insertBefore(this.draging, this.target); 66 } 67 this._anim(targetTop, this.target); 68 this._anim(dragingTop, this.draging); 69 } 70 }, 71 _anim(startPos, dom) { 72 let offset = startPos - dom.getBoundingClientRect().top; 73 dom.style.transition = 'none'; 74 dom.style.transform = `translateY(${offset}px)`; 75 76 //触发重绘 77 dom.offsetWidth; 78 dom.style.transition = 'transform .3s'; 79 dom.style.transform = ``; 80 //触发重绘 81 // setTimeout(()=>{ 82 // dom.style.transition="transform .3s"; 83 // dom.style.transform=``; 84 // },0) 85 clearTimeout(dom.animated); 86 87 dom.animated = setTimeout(() => { 88 dom.style.transition = ''; 89 dom.style.transform = ``; 90 dom.animated = false; 91 }, 300); 92 }, 93 onDragEnd(event) { 94 // console.log('drag end'); 95 let temp = Array.from(this.$refs.parentNode.childNodes); 96 let currentNodes = temp.filter(node => { 97 return node.nodeName === _LI_ 98 }) 99 let list = currentNodes.map((i, index) => { 100 let item = this.dataProvider.find(c => { 101 const unikey = i.getAttribute(this.valueKey); 102 const flag = c[this.valueKey] === unikey; 103 return flag; 104 }); 105 return item; 106 }); 107 108 this.$emit('sorted', list); 109 }, 110 _index(el) { 111 let domData = Array.from(this.$refs.parentNode.childNodes); 112 return domData.findIndex(i => i.innerText == el.innerText); 113 } 114 } 115 }; 116 </script> 117 118 <style lang="scss" scoped> 119 .list { 120 padding-inline-start: 0; 121 122 .list-item { 123 transition: 0.3s all ease-in; 124 padding: 12px; 125 border-bottom: 1px solid #dbdbdb; 126 list-style: none; 127 margin: 0px; 128 129 &:hover { 130 background-color: #dbdbdb; 131 } 132 } 133 } 134 </style>View Code
调用案例:
1 <template> 2 <div class="drag-list"> 3 <lilo-drag-list :dataProvider="dataProvider" draggable :valueKey="valueKey" @sorted="sorted"> 4 <template slot-scope='{ item, index }'> 5 <div> 6 <span class="list-item">index:{{ index }}</span> 7 <span class="list-item">id:{{ item.id }}</span> 8 <span class="list-item">name:{{ item.name }}</span> 9 <span class="list-item">address:{{ item.address }}</span> 10 </div> 11 </template> 12 </lilo-drag-list> 13 </div> 14 </template> 15 16 <script> 17 export default { 18 data() { 19 return { 20 draggable: true, //是否可拖动,默认为true 21 valueKey: 'id', //数据项的唯一标识 22 dataProvider: [ 23 { id: 'S001', name: '张三', address: '湖北省武汉市江岸区百步亭花园现代城3区' }, 24 { id: 'S002', name: '李四', address: '湖北省武汉市江岸区百步亭花园现代城3区' }, 25 { id: 'S003', name: '王五', address: '湖北省武汉市江岸区百步亭花园现代城3区' }, 26 { id: 'S004', name: '张飞', address: '湖北省武汉市江岸区百步亭花园现代城3区' }, 27 { id: 'S005', name: '关羽', address: '湖北省武汉市江岸区百步亭花园现代城3区' }, 28 { id: 'S006', name: '嬴政', address: '湖北省武汉市江岸区百步亭花园现代城3区' }, 29 { id: 'S007', name: '廉颇', address: '湖北省武汉市江岸区百步亭花园现代城3区' }, 30 { id: 'S008', name: '蒙恬', address: '湖北省武汉市江岸区百步亭花园现代城3区' }, 31 { id: 'S009', name: '韩非', address: '湖北省武汉市江岸区百步亭花园现代城3区' } 32 ] 33 } 34 }, 35 methods: { 36 sorted(list) { //拖动完成之后触发 37 console.log(list) //改变后的数组顺序 38 console.log(this.dataProvider) //原数据顺序不会被改变 39 } 40 } 41 } 42 </script> 43 44 <style lang="scss" scoped> 45 .drag-list { 46 padding: 10px; 47 .list-item { 48 margin: 0 5px; 49 } 50 } 51 </style>
标签:Vue,target,dom,list,address,darg,id,name From: https://www.cnblogs.com/loveFlex/p/17662951.html