项目场景:
在多数后台管理系统中都会有dom-tree树形选择组件的需求, 所以对elementUI的el-tree做了二次封装
解决方案:
二次封装需要完成的目标
- 让组件可复用
- 满足项目基本需求
- 兼容多种使用场景
<template>
<div class="select-city">
<el-input
v-if="showFilter"
placeholder="请输入搜索城市"
v-model="filterText">
</el-input>
<el-tree
ref="tree"
class="select-city-tree"
:style="{'max-height': maxHeight + 'px'}"
:data="treeList"
show-checkbox
node-key="id"
highlight-current
:default-expanded-keys="expandedKeys"
:default-checked-keys="keys"
:props="defaultProps"
:filter-node-method="filterNode"
@check-change="handleNodeClick">
</el-tree>
</div>
</template>
<script>
export default {
name: 'selectCity',
/**
* treeList => 数据列表
* checkedKeys => 选中的数据
* expandedKeys => 父级选中数据(一般不用传, 组件会根据子集自动选中父级)
* resetScroll => 重置滚动条(仅在弹窗上有效,关联弹窗的status)
* showFilter => 是否开启tree顶部搜索框
* 禁用需要在tree里面使用disabled进行禁用
*/
props: {
treeList: {
type: Array,
default: () => [],
/*
数据结构为{
label: 'title',
id: 1,
children: [子集]
}
*/
},
checkedKeys: {
type: Array,
default: () => []
},
expandedKeys: {
type: Array,
default: () => []
},
// 是否重置滚动条
resetScroll: {
type: Boolean,
default: false
},
// 是否开启筛选
showFilter: {
type: Boolean,
default: false
},
// 是否需要父级id
hasParent: {
type: Boolean,
default: false
}
},
data () {
return {
// 这里写死了一个显示的key, 如需改动需要将这个通过props暴露出去
defaultProps: {
children: 'children',
label: 'label'
},
maxHeight: 500,
filterText: '',
keys: []
}
},
mounted () {
this.keys = this.checkedKeys.length ? [...this.checkedKeys] : []
// 根据浏览器高度来确定显示的最大高度
this.maxHeight = parseInt(document.documentElement.clientHeight * 0.4)
},
watch: {
// 重置滚动条
resetScroll (value) {
if (value) {
this.$refs.tree.$el.scrollTop = 0
this.filterText = ''
}
},
filterText (val) {
this.$refs.tree.filter(val)
},
// 重置内容
checkedKeys (val, oldVal) {
this.keys = this.checkedKeys.length ? [...this.checkedKeys] : []
const flag = JSON.stringify(val) === JSON.stringify(oldVal)
if (!this.checkedKeys.length && flag) {
this.$nextTick(() => {
this.$refs.tree.setCheckedKeys([])
})
}
}
},
methods: {
/**
* 在用户选择城市的时候会有几种情况出现
* 通过this.$refs.tree.getCheckedKeys()方法去获取当前选中按钮的code,
* 去掉选项中的省份的code, 然后传给父级
*/
handleNodeClick (data, checked) {
// console.log(data, checked)
let removalList = this.$refs.tree.getCheckedKeys()
let tempSelectList = [...removalList]
if (!this.hasParent) {}
this.$emit('treeChange', tempSelectList)
},
filterNode (value, data) {
if (!value) return true
return data.label.includes(value)
}
}
}
</script>
<style lang="less">
.select-city {
.el-checkbox__input.is-disabled.is-checked .el-checkbox__inner {
background-color: #409EFF;
border-color: #409EFF;
}
.el-checkbox__input.is-disabled.is-checked .el-checkbox__inner::after {
border-color: #fff;
}
.el-checkbox__input.is-disabled.is-indeterminate .el-checkbox__inner {
background-color: #409EFF;
border-color: #409EFF;
}
}
</style>
<style lang="less" scoped>
.select-city {
padding: 10px 0;
overflow: auto;
.select-city-tree {
overflow: auto;
margin-top: 12px;
}
}
</style>