首页 > 其他分享 >Vue【原创】可拖动列表 darg-list

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

时间:2023-08-28 17:46:20浏览次数:38  
标签:Vue target dom list address darg id name

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

相关文章

  • View与Widget,以QListView与QListWidget为例
    目录View与Widget的区别和联系如何正确使用QListView与QListWidget使用QListView:使用QListWidget:代码演示总结在Qt框架中,"View"与"Widget"是两个关键概念,它们在用户界面设计和数据展示中发挥重要作用。本篇博客将介绍"View"和"Widget"的区别与联系,然后使用Qt中的QListView和QList......
  • vue 监听窗口变化
    mounted(){window.onresize=()=>{return(()=>{this.$nextTick(()=>{if(document.documentElement.clientWidth<=1000){this.mode="vertical"}else{......
  • Newtonsoft.Json:JObject 动态添加字段/List<JObject>转DataTable
    1.JObject动态添加字段;varjsonObject=newJObject();foreach(varkeyinKeys){jsonObject.Add(key,value);}jsonObject.Add("*****","1");2. List<JObject>转DataTable1): 首先List<JObject>转stringList<JObject>jso......
  • C#里面设置ListView单列(某个单元格的样式:颜色和字体等
    C#里面设置ListView单列(某个单元格的样式:颜色和字体等)。                ListViewItemlvi=newListViewItem((i+1).ToString());               lvi.UseItemStyleForSubItems=false;                ListViewItem.......
  • 关于 Vue.js v2 和 v3 生命周期的概述以及它们之间的区别
    Vue.jsv2的生命周期包括以下阶段:1、beforeCreate:在实例初始化之后、实例数据观测和事件配置之前被调用。2、created:实例已经创建完成,数据观测和事件配置已完成,但尚未挂载到DOM上。3、beforeMount:在挂载之前被调用,相关的render函数首次被调用。4、mounted:实例已......
  • 百度:为vue站添加百度统计
    一,登录百度统计获取统计代码:使用设置->网站列表->新增网站:填写数据后点确定:配置单页:复制代码:二,添加代码到vue的html页面12345678910111213141516171819202122232425262728293031323334353637<!DOCTYPEhtml><......
  • Vue【原创】日历组件
    最近项目中封装了一个日历组件,用于节假日管理,支持输入默认选中的日期,选择管理日期。效果图: calendar组件:1<template>2<divclass="calendar">3<slotname="title">4<divclass="calendar-title">{{curYearMont......
  • Vue3 使用Vuex与Vuex-persistedstate
    Vuex与vuex-persistedstateVuex是什么?Vuex是一个用于Vue.js应用程序的状态管理模式。它使得在应用程序中的所有组件之间共享和访问状态变得非常简单。Vuex将应用程序的状态存储在一个单一的存储库中,并且提供了一组用于更改状态的API。这使得状态管理变得更加可预测和易于调试。......
  • vue element 多个Form 表单同时验证
     多个Form内容统一提交验证1<el-formref="form1"></el-form>2<el-formref="form2"></el-form>3<el-formref="form3"></el-form>4<el-formref="form4"></el-form>......
  • vue3同一页面内重复引用同一操作dom的组件产生的问题
    [2023年8月28日12:39:40]vue3同一页面内标签<component>重复引用同一组件,且该组件内使用css选择器进行dom操作导致页面内相同组件发生变化的问题解决记录组件内进行dom操作,需要通过js方法进行选择器的元素获取,但当vue3全部渲染完毕后,页面内有多个id为test9的相同元素,元素选择将......