Binyy Wuhan

i love Flex i come from Wuhan

导航

Vue【原创】可拖动列表 darg-list

可拖动排序的列表 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>

 

posted on 2023-08-28 17:33  Binyy_Wuhan  阅读(139)  评论(0编辑  收藏  举报