昨晚加班写的穿梭框组件,一边写一边遇到bug,果然只有bug才会让你印象更深刻,更值得记录
封装成组件FreezeTransfer
效果如下:
主要参考了官网上可搜索的这个示例
先说遇到的bug,然后贴完整的代码
1、el-transfer数据源绑定之后不展示,filterMethod不对的原因
2、点单个复选框,所有项都被选中,数据被处理后,不需要再 使用props转换
:props=“{
key: ‘id’,
label: ‘cnName’
}”
转换
3、未选择的时候,中间按钮的左右箭头不显示
4、行没有占全
5、每次打开弹窗的时候,初始化
6、change事件的使用
7、清空某个面板的搜索关键词
1、先说第一个绑数据源,按官网给的示例,这个和treeselect的示例差不多,需要将格式转换成它要求的格式
正常从接口获取数据就行,我这里是组件,所以在父页面获取到之后,传到子组件就行,在子组件里监听数据源,处理数据之后给treansfer绑定的data
dataSource: {handler(newVal) {this.source = newVal.map(item => {let obj = {key: item.code,code: item.code,label: item.cnName,disabled: false,}return obj})this.$emit('getCode', [])},deep: true,immediate: true,},
这里遇到的bug就是左侧的数据源已经有了,但就是什么都不展示,一片空白
这个坑就是filter-method引起的,因为我是可搜索的穿梭框,从官方示例拿过来的时候,先定义了这个方法,但是啥都没写,真的是不踩一下根本不知道这还会影响数据源的展示
:filter-method="filterMethod"
filterMethod(query, item) {
//模糊查询,不区分英文大小写return item.key.toUpperCase().indexOf(query.toUpperCase()) > -1 || item.label.indexOf(query) > -1},
2、点单个复选框,所有项都被选中,可能的原因就是id都绑了一样的,但我排查了不是这个原因,这也是个坑,就是数据源处理过了之后,不需要再写props转换了
不需要
:props="{key: 'id',label: 'cnName'}"
3、未选择的时候,中间按钮的左右箭头不显示
官网未选择的时候
我这里没有中间的箭头,可能是样式受影响了
/deep/ .el-button.el-button--primary.is-disabled {color: #fff !important;
}
4、行没有占全
/deep/ .el-transfer-panel__item.el-checkbox {width: 100%;
}
5、每次打开弹窗的时候,初始化
因为是放在弹窗中展示的,每次打开弹窗要初始化数据
父组件上定义initTransarr数组,在确认及取消事件中置为空
:initTransarr="initTransarr"initTransarr:[]/** 弹框确认取消 */dialogSure(flag) {if (flag === 'sure') {this.$emit('handleSure', this.custCodearr)}} else {this.$emit('handleCancel')}this.initTransarr = []this.$emit('update:visible', false)},
6、change事件的使用
这里说下,left-check-change和right-check-change,分别在左侧和右侧勾选复选框的时候触发,我这里因为需求的调整,没用到,但还是保留了
change事件三个参数,当前值、数据移动的方向(‘left’ / ‘right’)、发生移动的数据 key 数组,就是中间左右箭头的事件
7、清空某个面板的搜索关键词
父组件
<FreezeTransferv-if="isTransfer"ref="freezeTransfer":visible="visible":dataSource="dataSource":initTransarr="initTransarr"@getCode="getCode"></FreezeTransfer>
data() {return {visible:false,custCodearr: [],initTransarr: [],}},
getCode(arr) {this.custCodearr = arr},
/** 弹框确认取消 */dialogSure(flag) {if (flag === 'sure') {this.$emit('handleSure', this.custCodearr)}} else {this.$emit('handleCancel')}this.initTransarr = []this.$emit('update:visible', false)},
子组件
<template><div class="transfer"><el-transferv-if="visible"ref="transfer"filterable:filter-method="filterMethod":filter-placeholder="$t('placeholderName.enter')"v-model="value":data="source":titles="['可选择', '已选择']"@change="handleChange"@left-check-change="leftcheckChange($event)"@right-check-change="rightcheckChange($event)"><span slot-scope="{ option }">{{ option.code }} - {{ option.label }}</span></el-transfer></div>
</template><script>
export default {name: 'FreezeTransfer',props: {// 列表显示隐藏visible: {type: Boolean,default: false,},// 列表数据dataSource: {type: Array,default: () => {return []},},// 初始化右侧数据initTransarr: {type: Array,default: () => {return []},},},data() {return {source: [], // 总数据value: [],}},watch: {initTransarr: {handler(newVal) {this.value = newVal},deep: true,},dataSource: {handler(newVal) {this.source = newVal.map(item => {let obj = {key: item.code,code: item.code,label: item.cnName,disabled: false,}return obj})this.$emit('getCode', [])},deep: true,immediate: true,},},mounted() {},methods: {filterMethod(query, item) {return item.key.toUpperCase().indexOf(query.toUpperCase()) > -1 || item.label.indexOf(query) > -1},//当前值、数据移动的方向('left' / 'right')、发生移动的数据 key 数组handleChange(value, direction, movedKeys) {if (direction == 'right') {this.$nextTick(() => {this.$refs.transfer.clearQuery('left')})} else if (direction == 'left') {this.$nextTick(() => {this.$refs.transfer.clearQuery('right')})}var arr = []value.forEach(item => {arr.push({ code: item })})this.$emit('getCode', arr)},leftcheckChange(e) {// console.log(e,'left------');},rightcheckChange(e) {// console.log(e,'right------');},},
}
</script><style scoped lang="scss">
.transfer {width: 100%;/deep/ .el-transfer-panel {width: 45%;}
}
/deep/ .el-button.el-button--primary.is-disabled {color: #fff !important;
}
/deep/ .el-transfer-panel__item.el-checkbox {width: 100%;
}
/deep/ .el-transfer-panel__list {height: 480px !important;
}
/deep/ .el-transfer-panel__body {height: 480px !important;
}
</style>