近期项目中遇到穿梭框功能,将其过程做以总结:
效果图

思路
- 获取左侧勾选的值(checkedList)
- 将checkedList循环一遍push进右侧(rightList)
- 把leftList和rightList做一遍过滤遍历 使用
filter
和some
函数来过滤去重 这样是为了避免已经添加到右侧之后左侧还有对应的城市
代码
item.vue
<template>
<el-card class="item">
<div class="header">
<el-row :gutter="16">
<!-- <el-col span="12"> <el-select></el-select></el-col>
<el-col span="12"> <el-select></el-select></el-col>
<el-col span="12"> <el-select></el-select></el-col>
<el-col span="12"> <el-input placeholder="单位名称"></el-input></el-col> -->
</el-row>
</div>
<div class="checkAll">
<el-checkbox
:isIndeterminate="isIndeterminate"
v-model="checkAll"
@change="handleCheckAllChange"
>全选</el-checkbox
>
<span>{{ checkedCompanies.length }}/{{ checkList.length }}</span>
</div>
<div class="checkbox">
<el-checkbox-group
v-model="checkedCompanies"
@change="handleCheckedCitiesChange"
>
<el-checkbox
class="checkItem"
v-for="item in checkList"
:label="JSON.stringify(item)"
:key="item.companyId"
>{{ item.companyName }}</el-checkbox
>
</el-checkbox-group>
</div>
</el-card>
</template>
<script>
export default {
name: 'TransferItem',
components: {},
props: {
checkList: {
type: Array,
default: () => []
}
},
data() {
return {
checkedCompanies: [],
checkAll: false,
isIndeterminate: true
}
},
computed: {},
methods: {
// 全选
handleCheckAllChange(val) {
// 因为后端需要id和name 所以label绑定的是把item转成对象
const arr = this.checkList.map((item) => JSON.stringify(item))
this.checkedCompanies = val ? arr : []
this.isIndeterminate = false
this.$emit('change', this.checkList)
},
// 单选
handleCheckedCitiesChange(value) {
let checkedCount = value.length
this.checkAll = checkedCount === this.checkList.length
this.isIndeterminate =
checkedCount > 0 && checkedCount < this.checkList.length
const arr = value.map((item) => JSON.parse(item))
this.$emit('change', arr)
},
// 清除勾选状态
clearCheck() {
this.checkedCompanies = []
this.checkAll = false
this.isIndeterminate = true
}
},
created() {},
mounted() {}
}
</script>
<style lang="scss" scoped>
.item {
width: 340px;
height: 330px;
.header {
padding: 0 12px;
padding-top: 8px;
.el-col {
margin-bottom: 8px;
}
}
.checkAll {
background: #f7f8fa;
color: #7d8292;
font-size: 12px;
height: 40px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px;
}
.checkbox {
height: 200px;
overflow: auto;
/deep/ .el-checkbox-group {
display: flex;
flex-direction: column;
.checkItem {
margin-right: 0px;
height: 40px;
padding: 0 12px;
color: #424656;
font-size: 12px;
line-height: 40px;
border-bottom: 1px solid #f2f2f2;
}
}
}
}
</style>
header里面可以放需要的查询条件
Transfer.vue
<template>
<div class="Transfer">
<div class="left">
<Item ref="left" :checkList="leftList" @change="leftChange" />
</div>
<div class="btn">
<el-button type="primary" style="margin-bottom: 60px" @click="add()"
>>添加</el-button
>
<el-button style="margin: 0" @click="remove()"><删除</el-button>
</div>
<div class="right">
<Item ref="right" :checkList="rightList" @change="rightChange" />
</div>
</div>
</template>
<script>
import Item from './components/Item.vue'
import { deepClone, filterData } from '@/utils/index'
export default {
name: 'Transfer',
components: { Item },
props: {
checkLeftList: {
type: Array,
default: () => []
},
checkRightList: {
type: Array,
default: () => []
}
},
data() {
return {
// 左边列表
leftList: [],
// 左边选中
leftChecked: [],
rightList: [],
rightChecked: []
}
},
watch: {
checkLeftList: {
handler(v) {
if (v) {
this.leftList = deepClone(v)
}
},
deep: true,
immediate: true
},
checkRightList: {
handler(v) {
if (v) {
this.rightList = deepClone(v)
}
},
deep: true,
immediate: true
}
},
computed: {},
methods: {
leftChange(checked) {
this.leftChecked = checked
},
rightChange(checked) {
this.rightChecked = checked
},
// 添加
add() {
// 把左侧勾选的值添加到右侧
this.leftChecked.forEach((v) => {
if (v) this.rightList.push(v)
})
// 拿左侧的值和右侧的值做一遍过滤遍历
this.leftList = filterData(
this.leftList,
this.rightList,
'companyId',
'companyId'
)
this.$refs.left.clearCheck()
},
remove() {
this.rightChecked.forEach((v) => {
if (v) this.leftList.push(v)
})
this.rightList = filterData(
this.rightList,
this.leftList,
'companyId',
'companyId'
)
this.$refs.right.clearCheck()
}
},
created() {},
mounted() {}
}
</script>
<style lang="scss" scoped>
.Transfer {
display: flex;
.left,
.right {
border: 1px solid #eaecf1;
}
.btn {
width: 100px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
}
</style>
过滤函数
// 2个数组过滤重复数据
/**
*
* @param {Array} arr1 数组1
* @param {Array} arr2 数组2
* @param {String||Number} arr1key 数组1的key
* @param {String||Number} arr2key 数组2的key
* @returns Array
*/
export function filterData(arr1, arr2, arr1key, arr2key) {
return arr1.filter(
(item) => !arr2.some((ele) => ele[arr2key] === item[arr1key])
)
}
网友评论