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& ...
随机推荐
- phpstudy-sqlilabs-less-11
题目:POST - Error Based - Single quotes- String 基于错误的单引号post型字符变形的注入 看到有个账密输入口第一反应尝试post注入 打开post data ...
- flutter填坑之旅(环境搭建篇--mac系统)
上次配置过Mac到flutter环境,但是由于最近系统更新了,什么都没了又得从新配置,发现自己竟然好多都忘记了,看来还是得把它记下来才行 在Mac上安装并运行Flutter 最低要求: 操作系统:ma ...
- [C#]插件编程框架 MAF 开发总结
1. 什么是MAF和MEF? MEF和MEF微软官方介绍:https://learn.microsoft.com/zh-cn/dotnet/framework/mef/ MEF是轻量化的插件框架,MA ...
- Odoo-----计算字段、depnds,onchange 机制、模型约束
1 计算字段和默认值问题 字段通过调用模型的方法的实时计算获得,一般都是 compute 属性为主的方法,这个计算方法通过计算self每条记录设置的的值,self 是一个有记录的有序集合,支持py ...
- Linux 中 3 个文件打包上传和下载相关命令详解
tar 命令 通过 SSH 访问服务器,难免会要用到压缩,解压缩,打包,解包等,这时候tar 命令就是必不可少的一个功能强大的工具.Linux 中最流行的tar是麻雀虽小,五脏俱全,功能强大. 使用t ...
- BGP选路
实验拓扑 实验需求 现有三个自治系统,需要对R1访问R4的loopback-X数据走向进行精确控制: R1访问R4的loopback0走R2,通过在R1上修改本地优先级实现 R1访问R4的loopba ...
- .NET周报 【6月第4期 2023-06-25】
国内文章 如何在long-running task中调用async方法 https://www.cnblogs.com/eventhorizon/p/17497359.html long-runnin ...
- k8s部署springboot
综述 首先介绍发布步骤. 1.从代码仓库下载代码,比如GitLab: 2.接着是进行打包,比如使用Maven: 3.编写Dockerfile文件,把步骤2产生的包制作成镜像: 4.上传步骤3的镜像到远 ...
- WPF入门教程系列三十 ——DataGrid验证
WPF入门教程系列目录 WPF入门教程系列二--Application介绍 WPF入门教程系列三--Application介绍(续) WPF入门教程系列四--Dispatcher介绍 WPF入门教程系 ...
- LaTeX 的学习笔记
摘自我的洛谷博客 该文章被打开的次数(包括洛谷平台): \(\LaTeX\) 中所有命令都以\开头,后面可以跟一个花括号,代表参数. \documentclass{} 指定了文章类型,有 articl ...