Vue2.x实现自定义列表和列表拖动排序并展示
一、问题
- 列表通过编辑页面可以对表头信息进行拖动编辑,编辑内容包括:排序列表的顺序、列表每一列是否需要展示
- 总体规划为两大需求:拖动排序列表、根据排序好的表头顺序展示对应的列表信息
二、解决
1.解决自定义列表拖动排序
-
首先,解决拖动排序的问题,因为是
Vue
项目,所以可以利用组件库中vuedraggable
组件对列表进行拖动排序 -
下载
vuedraggable
组件(使用cnpm
同理)npm install vuedraggable -S
-
在需要使用该组件的页面进行引入,并且注册,引入使用方式与自定义组件使用方式类似,这里是
headTitleEdit.vue
界面引入使用的:import draggable from 'vuedraggable' ... components: { draggable }
-
将该组件嵌套到需要进行拖动排序的列表的外层,并且使用
v-model
指令绑定需要排序的列表数据(这里是一个数组);同样组件支持使用语法糖@update
绑定一个函数,列表拖动改变顺序后会触发该函数,返回新索引和旧索引;通过绑定动态属性:options="{animation:300}"
可以改变动画效果,列表的template
部分代码如下:<div class="edit-card-contian"> <draggable v-model="titleList" @update="datadragEnd" :options="{animation:300}" > <div class="edit-title-item" v-for="item in titleList" :key="item.id" > <span :class="item.isCheck?'edit-title-select':''">{{item.name}}</span> <div> <el-checkbox v-model="item.isCheck"></el-checkbox> <i class="el-icon-s-unfold"></i> </div> </div> </draggable> </div>
-
通过本地模拟数据进行演示,简单看一下自定义列表的数据结构,其中
field_name
是后面对列内容进行排序的关键data() { return { ... titleList: [{ id: 1, name: '姓名', field_name: 'name', isCheck: true, }, { id: 2, name: '年龄', field_name: 'age', isCheck: true, }, { id: 3, name: '性别', field_name: 'sex', isCheck: true, }, { id: 4, name: '职业', field_name: 'position', isCheck: true, }, { id: 5, name: '期望薪资', field_name: 'pay', isCheck: true, }], // 列表项 }; }
-
页面的展示效果如下:
-
当拖动列表更换位置后,触发
@update
所绑定的事件,这里打印出列表数据,查看更换位置后的列表数据,可以看到数组顺序与拖动后的顺序保持一致:
-
将数据通过点击确定或者保存之类的事件传递给后端进行保存,方便在后续的自定义列表页面使用,说一下这里如果
checkbox
不勾选只是改变当前对应数据isCheck
的值,依然会保存在数组中,到这里拖动排序的问题就都解决了!
2.解决根据表头数据展示自定义列表数据
-
这个需求的难点在于如何根据表头数据的顺序展示列表的内容,利用表头数据中的
field_name
字段,这是进行展示的关键所在,表单数据内容如下,依然为模拟数据:data() { return { ... bodyList: [ { id: 1, name: '小明', age: 22, sex: '男', position: '前端工程师', pay: '11K' }, { id: 2, name: '小红', age: 23, sex: '男', position: '产品经理', pay: '15K' }, { id: 3, name: '小丽', age: 22, sex: '男', position: '架构师', pay: '21K' }, { id: 4, name: '小强', age: 21, sex: '男', position: '后端工程师', pay: '18K' }, { id: 5, name: '小刚', age: 25, sex: '男', position: '后端工程师', pay: '16K' } ], } }
-
template
中表头利用v-for
循环进行展示,列表内容部分则需要利用双重v-for
循环,第一层遍历列表内容数据bodyList
,第二层使用template
包裹循环表头数据titleList
,代码如下:<!-- 列表部分 --> <div class="ca-contain"> <!-- 列表表头 --> <div class="long-list list-title"> <span v-for="item in titleList" :key="item.id" >{{item.name}}</span> <span>操作</span> </div> <!-- 列表表体 --> <div class="long-list list-body" v-for="item in bodyList" :key="item.id" > <template v-for="headItem in titleList"> <span :title="item[headItem.field_name]" :key="headItem.field_name" >{{item[headItem.field_name]}}</span> </template> <span class="operate"> <i class="iconfont icon-shanchu" @click="delCur(item)" ></i> </span> </div> </div>
-
其中样式给表头和表体每个
div
一个最小宽度即可,超出部分显示省略号,样式如下图所示不做赘述:
-
到这里列表的内容按照自定义列表中表头数据的顺序显示已经完成了,最后做的只是判断当前的字段是否选中(展示),也就是
isCheck
是否为true
,这里可以根据自己喜好,可以在循环中使用三木,也可以如下通过filter
进行过滤,代码如下:this.titleList.filter(({ isCheck }) => { return isCheck == true })
-
最终效果如下:
以上就完成了自定义表单的所有需求了,如有更好的方法,欢迎补充讨论🌈