左边代码结构,为模板库 templateList 是组件
<el-col :span="6" style="margin-right: 15px;">
<div class="title">
<h1>模板库</h1>
<span>可选中模板拖拽至页面中</span>
<div class="draggableList">
<draggable v-model="templateList" class="list-group" v-bind="dragOptions1">
<transition-group>
<div v-for="item in templateList" :key="item.localFloorName" class="wrap">
<el-card shadow="hover">
<img :src="item.img" alt="" class="cardImg" />
</el-card>
</transition-group>
</draggable>
</el-col>
3.右边结构
<el-col :span="6" style="margin-right: 15px;">
<div class="title">
<h1>页面编辑</h1>
<el-link type="primary" @click="setup">设置预览用户</el-link>
<div class="draggableList">
<draggable v-model="listRight" class="list-group" v-bind="dragOptions2" @add="updateHandler" @update="rightEnd">
<div v-for="(item, key) in listRight" :key="key" class="wrap" :class="{ 'current-select': item === componentData }">
<el-card shadow="hover">
<div class="imIwrap" v-if="item">
<div @click="editCompnent(item)" v-for="res in visualization" :key="res.id">
<component v-if="item.floorType === res.id" :dataInfo.sync="item" :is="res.path" />
<!-- <img :src="item.img" alt="" @click="editCompnent(item)" class="cardImg" /> -->
<i class="el-icon-delete delet" @click="deletComponents(key, item)"></i>
<i class="el-icon-top up" v-if="item.floorType !== 1 && item.floorType !== 13 && hasUpArrow(key)" @click="up(item, key)"></i>
<i class="el-icon-bottom down" v-if="item.floorType !== 1 && item.floorType !== 13 && hasDownArrow(key)" @click="down(item, key)"></i>
</el-card>
</draggable>
</el-col>
computed: {
dragOptions1() {
return {
animation: 0,
group: {
name: 'description',
pull: 'clone',
put: false
ghostClass: 'ghost'
dragOptions2() {
return {
animation: 0,
group: 'description'
* 删除某个楼层
async deletComponents(v, item) {
try {
await this.deleteFloorByIdFun(item.floorId)
await this.initData()
} catch (err) {
console.log(err)
* 上移楼层
async up(data, index) {
// TODO: 边界情况处理 楼层索引和orderVal值的关系
console.log(data, index)
await this.modifyAppPageFloorOrderValFun(data.floorCode, index)
this.initData()
* 楼层下移
async down(data, index) {
// TODO: 边界情况处理 楼层索引和orderVal值的关系
console.log(data, index)
await this.modifyAppPageFloorOrderValFun(data.floorCode, index + 2)
this.initData()
// 组件拖拽完成
async updateHandler(evt) {
let { newIndex: newDraggableIndex } = evt
const moveData = this.listRight[newDraggableIndex]
this.sortListRight() // 数据可能重新排序
newDraggableIndex = this.listRight.indexOf(moveData) // 重新根据数据找回索引位置
newDraggableIndex++ // 楼层排序默认从1开始
try {
const { data: newFloorCode } = await this.createAppPageFloorFun(moveData.floorType, newDraggableIndex, moveData.navigationType)
await this.initData(newFloorCode)
this.componentsName = moveData.localFloorName
this.tableComponent = moveData.components
} catch (err) {
this.listRight.splice(newDraggableIndex, 1)
// 右边移动
async rightEnd(evt) {
let { newIndex: newDraggableIndex } = evt
const moveData = this.listRight[newDraggableIndex]
this.sortListRight() // 数据可能重新排序
newDraggableIndex = this.listRight.indexOf(moveData) // 重新根据数据找回索引位置
newDraggableIndex++ // 楼层排序默认从1开始
console.log(moveData, 'moveData')
await this.modifyAppPageFloorOrderValFun(moveData.floorCode, newDraggableIndex++)
this.initData()
// 具体编辑某组件
editCompnent(v) {
if (v.floorId) {
this.componentData = v
const { components, localFloorName } = v
this.tableComponent = components
this.componentsName = localFloorName
1. 不多说直接看图片明了:(线上项目)2.开始上代码:左边代码结构,为模板库templateList 是组件<el-col :span="6" style="margin-right: 15px;"> <div class="title"> <h1>模板库</h1> <span>可选中模板拖拽至页面中</span> </div> <div ..
Element UI 提供了大部分UI控件,但对于
拖拽,确实是个短板,于是就需要额外的控件来补充了,即本文档的主角
vuedraggable。
从实战角度,以低代码配置功能为例,说明
vuedraggable的属性、方法、用法,以及使用过程中遇到的一些坑点及解决方案。
要点如下:
group属性的要点
update和sort事件的差别
add事件如何获取数据
如何处理属性重复添加问题
不同
列表间拖动group属性无效
某个业务实体,如用户管理,常见的菜单对应一个
列表页面,顶部为页面级功能按钮,如新增、
删除、导出等,中间为查询区域,可以放几个常用的查询条件,最下面则是查询结果,以表格形式展现行列数据。查询结果表格的行记录,最后一列放一些针对于该行数据的快捷按钮,如
删除、
编辑等。
这个配置功能,一方面涉及到元素的排序,如按钮的次序、查询条件的次序、查询结果中列的次序;另一方面涉及到
列表间元素的移动,如将实体属性添加到查询
列表或查询结果中。如采用传统模式,需要选中某个元素,点击左移、右移等按钮,既不直观,操作也繁琐。而采用
拖拽式操作,所见即所得,用户体验大幅提升。
今天分享一个vue项目中在不同列表拖拽设置选项的功能,这个功能也是在做项目中遇到的,先说下这个功能的要点(参考下图),有2个列表,左侧列表展示已选,右侧列表展示未选,通过拖拽进行设置,已选的选项不能超过4个,超过的话自动将拖拽之前的最后一项清除到右侧,且如果从已选往未选里拖的时候,右侧显示垃圾桶的提示(如图)。
拖拽功能图片:
垃圾桶显示图:
首先讲讲vue-draggable的使用
安装vue-draggable:
npm install vuedraggable
在使用插件的组件内引
录屏软件:screenToGif (将视频转为Gif,我认为简单又好操作)
我深知,文字的感知不如图片,图片的感知不如视频,所以希望在每一次的记录中,都有种收货与喜悦,虽然以前用过这个插件,相当强大的插件,但第一次从0到1,所以记录美好时刻~
1.多列之间想要互相拖动
要有相同的name,如:name:'site'
2.多列直接想要拷贝,不移除
Sortable.js插件的配置信息
vue.
draggable的clone拷贝
实现常用菜单功能
本文参考文章 记录一下
vuedraggable clone的坑,获取数据
前排提示: 如果你也遇到了
编辑拖拽的单元数据时,原单元数据也跟着发生了变化,可以直接拖到最后看解决方法。
要
实现的效果
有
两个列表:
列表A为预设的组件,不能添加
编辑和
删除;
列表B为
编辑区域,需要从
列表A中
拖拽组件,然后修改组件名称等一些信息。
通过分析需求,我们可以知道:
列表A和B的group name需相同;
1.group 可以传入对象:object:{name,pull,put}
2.name两个draggable节点中, group 的 name 是一样的, 就可以实现两个区域的相互拖拽.::group='{name: "menu", put: true}'
3.pull:pull用来定义从这个列表容器移动出去的设置,true/false/'clone'/function tr...