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>
调用案例:
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【原创】可拖动列表 darg-list的更多相关文章
- vue+mousemove实现拖动,鼠标移动过快拖动就失效
今天用vue+原生js的mousemove事件,写了个拖动,发现只能慢慢拖动才行,鼠标只要移动快了,就失效,不能拖动了: 搞了半天在,总算解决了,但是问题的深层原理还没搞清楚,知道的大侠可以留言分享, ...
- vue实现购物清单列表添加删除
vue实现购物清单列表添加删除 一.总结 一句话总结: 基础的v-model操作,以及数组的添加(push)删除(splice)操作 1.checkbox可以绑定数组,也可以直接绑定值? 绑定数组就是 ...
- vue指令实现拖动的高级写法
不熟悉vue自定义指令看这里: https://cn.vuejs.org/v2/guide/custom-directive.html vue指令实现拖动方法很方便也挺简单,但是网上大部分的教程代码, ...
- Android 可拖动列表项的ListView
需求分析 一个界面内两个ListView 我关注的栏目列表 上面的要长按后可拖动排序 点击减号后列表项消失 下面列表增加一行 同时存储相应字符串到本地作为标记 未关注栏目列表 普通ListView 点 ...
- vue v-nav指令属性列表
v-nav指令属性列表 属性名 属性描述 类型 必选 默认 title 导航栏标题 String No 空字符串 showBackButton 是否显示(左边的)返回按钮 Boolean No fal ...
- VUE通过id从列表页跳转到相对的详情页
新闻列表页面: 在这里我用a标签进行跳转,在vue里面可以这样写<router-link></router-link> 1 <router-link :to=" ...
- vue里面的v-for列表循环
列表渲染 v-for v-for可以把数据中的一个数组对应为一组元素v-for 指令需要以 item in items 形式的特殊语法, items 是源数据数组并且 item 是数组元素迭代的别名. ...
- Vue基础进阶 之 列表过渡
在前面的博客我们一直在操作单个元素的过渡,如果是对多个元素过渡,例如列表,这时就要用到<transition-group>这个组件了: 如何使用:将要操作的列表元素放在<transi ...
- vue 自学笔记(5) 列表渲染
列表渲染 一:v-for 指令 当我们涉及到列表渲染数据的时候,不可能做一个重复的工作去不停的一个一个的渲染每一项列表.并且列表数据的表现,比如从后端请求过来的数据,不可能是一个一个的单独的 JSON ...
- 【前端】Vue.js实现网格列表布局转换
网格列表布局转换 实现效果: 实现代码及注释: <!DOCTYPE html> <html> <head> <title>布局转换</title& ...
随机推荐
- idea过期解决
用作用作发现过期了,苦恼,好办直接 搞个code 就行 MNQ043JMTU-eyJsaWNlbnNlSWQiOiJNTlEwNDNKTVRVIiwibGljZW5zZWVOYW1lIjoiR1VPI ...
- 深入理解 apply()方法
apply(thisArg) apply(thisArg, argsArray) thisArg 在 func 函数运行时使用的 this 值.请注意,this 可能不是该方法看到的实际值:如果这个函 ...
- 代码随想录算法训练营Day55 动态规划
代码随想录算法训练营 代码随想录算法训练营Day55 动态规划| 392.判断子序列 115.不同的子序 392.判断子序列 题目链接:392.判断子序列 给定字符串 s 和 t ,判断 s 是否为 ...
- 生物信息培训之WGCNA-权重基因共表达网络分析
本文分享自微信公众号 - 生信科技爱好者(bioitee).如有侵权,请联系 support@oschina.cn 删除.本文参与"OSC源创计划",欢迎正在阅读的你也加入,一起分 ...
- Vue3从入门到精通(二)
vue3 侦听器 在Vue3中,侦听器的使用方式与Vue2相同,可以使用watch选项或$watch方法来创建侦听器.不同之处在于,Vue3中取消了immediate选项,同时提供了新的选项和API. ...
- 通用密钥,无需密码,在无密码元年实现Passkeys通用密钥登录(基于Django4.2/Python3.10)
毋庸讳言,密码是极其伟大的发明,但拜病毒和黑客所赐,一旦密码泄露,我们就得绞尽脑汁再想另外一个密码,但记忆力并不是一个靠谱的东西,一旦遗忘密码,也会造成严重的后果,2023年业界巨头Google已经率 ...
- 快上车,搭乘HUAWEI HiCar驶向未来
HUAWEI HiCar(以下简称HiCar)是华为提供的人-车-家全场景智慧互联解决方案,连接手机与车辆,充分发挥各自的优势属性,将手机的应用/服务生态延伸进车辆,实现以手机为核心的全场景体验.消费 ...
- 完全兼容DynamoDB协议!GaussDB(for Cassandra)为NoSQL注入新活力
摘要:DynamoDB是一款托管式的NoSQL数据库服务,支持多种数据模型,广泛应用于电商.社交媒体.游戏.IoT等场景. 本文分享自华为云社区<完全兼容DynamoDB协议!GaussDB(f ...
- 关于 axios 是什么?以及怎么用?
〇.前言 Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 Node.js 中.简单的讲就是可以发送 Get.Post 请求. 诸如 Vue.React.Angular 等前 ...
- [ESP] 使用Ayla API Reference配网和连Ayla云
示例用的文档及链接 US Dev Dashboard(查看oem-id和oem-key) https://dashboard-dev.aylanetworks.com/ Ayla API Refere ...