赞
踩
目前项目中需要实现一个可拖拽的穿梭框并且是要多选,看了网上很多资料只有单选拖拽, 自己动手丰衣足食吧!
首先在element组件库提供的穿梭框组件的基础上去增加拖拽功能
这里我们要用到一个第三方拖拽组件sortablejs
安装sortablejs
npm i sortablejs --save-dev
html代码
<div class="transferBox"> <el-transfer ref="transfer" v-model="inputForm.workingProcedure" :titles="['未选择工序', '已选择工序']" target-order="push" :props="transferProps" :data="transferData" @left-check-change="leftCheckChange" @right-check-change="rightCheckChange" > <span slot-scope="{ option }" draggable="!option.disabled" @dragstart="drag($event, option)" > {{ option.workingProcedureName }} </span> </el-transfer> </div>
js代码
data 数据
import Sortable from 'sortablejs' export default { data() { return { transferData: [], // 穿梭框数据 transferLeftCheckData: [], // 左侧选中数据 transferRightCheckData: [], // 右侧选中数据 draggingKey: '', // 当前拖拽项 inputForm:{ workingProcedure: [], }, transferProps: { // 配置项可根据数据源配置所选字段 key: 'workingProcedureId', // 穿梭框内容的值 label: 'workingProcedureName' // 穿梭框所显示的字段 } } },
mounted生命周期
在mounted里执行, 防止会获取不到ref报错
如果有特殊的触发方式可写在函数内
弹窗最好包裹在this.$nextTick内触发
mounted() { const transfer = this.$refs.transfer.$el const leftPanel = transfer.getElementsByClassName('el-transfer-panel')[0].getElementsByClassName('el-transfer-panel__body')[0] const rightPanel = transfer.getElementsByClassName('el-transfer-panel')[1].getElementsByClassName('el-transfer-panel__body')[0] const rightEl = rightPanel.getElementsByClassName('el-transfer-panel__list')[0] Sortable.create(rightEl, { onEnd: evt => { const { oldIndex, newIndex } = evt const temp = this.inputForm.workingProcedure[oldIndex] if (!temp || temp === 'undefined') { return } // 解决右边最后一项从右边拖左边,有undefined的问题 this.$set(this.inputForm.workingProcedure, oldIndex, this.inputForm.workingProcedure[newIndex]) this.$set(this.inputForm.workingProcedure, newIndex, temp) } }) const leftEl = leftPanel.getElementsByClassName('el-transfer-panel__list')[0] Sortable.create(leftEl, { onEnd: evt => { const { oldIndex, newIndex } = evt const temp = this.transferData[oldIndex] if (!temp || temp === 'undefined') { return } // 解决右边最后一项从左边拖右边,有undefined的问题 this.$set(this.transferData, oldIndex, this.transferData[newIndex]) this.$set(this.transferData, newIndex, temp) } }) leftPanel.ondragover = ev => { ev.preventDefault() } leftPanel.ondrop = ev => { ev.preventDefault() // 往左拉 const index = this.inputForm.workingProcedure.indexOf(this.draggingKey) if (index !== -1) { // 如果当前拉取的是选中数据就将所有选中的数据拉到左边选中框内 if (this.transferRightCheckData.indexOf(this.draggingKey) !== -1) { // 此处为多选执行 this.transferRightCheckData.reduce((arr, item) => { if (arr.indexOf(item) !== -1) { // 每次计算将相同的删掉 arr.splice(arr.indexOf(item), 1) } return arr }, this.inputForm.workingProcedure) this.transferRightCheckData = []// 清除右侧选中的 不然下次向左拉取时会有缓存 // 否则就只拉取当前一个 } else { this.inputForm.workingProcedure.splice(index, 1) } } } rightPanel.ondragover = ev => { ev.preventDefault() } rightPanel.ondrop = ev => { ev.preventDefault() // 右边框里没有当前key值的时候 向右拉 if (this.inputForm.workingProcedure.indexOf(this.draggingKey) === -1) { // 此处为多选执行 // 如果当前拉取的是选中数据就将所有选中的数据拉到右边选中框内 if (this.transferLeftCheckData.indexOf(this.draggingKey) !== -1) { this.inputForm.workingProcedure = this.inputForm.workingProcedure.concat(this.transferLeftCheckData) this.transferLeftCheckData = [] // 清除左侧选中的 不然下次向右拉取时会有缓存 } else { // 否则就只拉取当前一个 this.inputForm.workingProcedure.push(this.draggingKey) } } } },
methods方法
methods: {
drag(ev, option) {
// 赋值当前拖拽的唯一标识
this.draggingKey = option.workingProcedureId
},
leftCheckChange(val) {
// 穿梭框左侧多选选中
this.transferLeftCheckData = [...val]
},
rightCheckChange(val) {
// 穿梭框右侧多选选中
this.transferRightCheckData = [...val]
}
}
目前写出的效果勉强够用,但是多选拉取时的重影还未实现, 有想法的可以留言一块改进!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。