1.项目要实现树状的选择,element-ui里面有el-cascader级联选择器可以实现,但是产品不想要级联选择器的实现效果,这个时候就利用element-ui的组件进行了二次封装
2.效果图(有样式要求可以自己调整)
3.element-ui的引入和安装就不赘述了,官网地址
4.封装利用了el-select,el-input,el-tree来实现
5.代码实现,外层el-select来绑定已经选中的数据并回显,内层el-input来做筛选,绑定一个数据,通过监听这个绑定的数据的变化来调用el-tree的筛选的方法,el-tree主要是用来处理数据的选中与取消
6.完整的代码(已经封装为组件了,可以直接复制使用)
<template>
<div>
<div v-if="readOnly">
<el-tag v-for="(tag, index) in id" :key="index" class="mx-1" :closable="false" :disable-transitions="false">
{{ tag.labelName }}
</el-tag>
</div>
<div v-else>
<el-select style="width: 100%;" v-model="labels" multiple placeholder="请选择" @remove-tag="handdleRemoveTag">
<el-option :label="paramsQuery.label" :value="paramsQuery.id" style="height: auto" disabled>
<div>
<el-input placeholder="请输入筛选" v-model="filterValue" />
<el-tree :data="queryData" show-checkbox default-expand-all node-key="labelId" ref="trees" highlight-current
:check-strictly="true" @check="handdleChange" :filter-node-method="filterNode" :props="defaultProps" />
</div>
</el-option>
</el-select>
</div>
</div>
</template>
<script>
import { queryBusiLevelLabelApi } from '@/api/businessinfoApi.js';
export default {
props: {
// 接收父组件传过来的默认数据,用于回显
id: {
type: Array,
default() {
return []
}
},
// 接收父组件传过来的默认数据,用于回显
label: {
type: Array,
default() {
return []
}
},
// 接收父组件传过来的el-tree的数据源
data: {
type: Array,
default() {
return [{
id: 1,
label: '一级 1',
children: [{
id: 4,
label: '二级 1-1',
children: [{
id: 9,
label: '三级 1-1-1'
}, {
id: 10,
label: '三级 1-1-2'
}]
}]
}, {
id: 2,
label: '一级 2',
children: [{
id: 5,
label: '二级 2-1'
}, {
id: 6,
label: '二级 2-2'
}]
}, {
id: 3,
label: '一级 3',
children: [{
id: 7,
label: '二级 3-1'
}, {
id: 8,
label: '二级 3-2'
}]
}]
}
},
// el-tree的配置
defaultProps: {
type: Object,
default() {
return {
children: 'childernLabel',
label: 'labelName',
id: 'labelId'
}
}
},
readOnly: {
type: Boolean,
default: false
}
},
data() {
return {
// 接收父组件传来的id,label
ids: [],
labels: [],
paramsQuery: {
id: '',
label: ''
},
// 筛选框绑定的字段
filterValue: '',
// 如何本页面发送请求,本页面发送请求的数据源
queryData: []
}
},
watch: {
// 侦听filterValue 的变化,调用filter的方法
filterValue(val) {
this.$refs.trees.filter(val)
},
id: {
handler(val) {
console.log('val=======>', val);
if (Array.isArray(val) && val.length) {
let arrs = []
this.ids = []
this.labels = []
val.forEach(it => {
const foundObject = arrs.find(obj => obj.labelId === it.labelId && obj.labelName === it.labelName);
if (!foundObject) {
arrs.push(it)
this.ids.push(it.labelId)
this.labels.push(it.labelName)
}
})
if (this.readOnly) {
} else {
this.$refs.trees.setCheckedNodes([])
this.$refs.trees.setCheckedNodes(arrs)
}
}
},
deep: true
},
},
mounted() {
this.getData()
},
methods: {
// el-tree选中发生改变触发,node为改变的数据,chenked为是否选中,选中为true,反之false
handdleChange(checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys) {
console.log('==================>', checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys)
this.ids = checkedKeys.checkedKeys
this.labels = []
if (checkedKeys.checkedNodes.length) {
checkedKeys.checkedNodes.forEach(item => {
this.labels.push(item.labelName)
})
}
const params = {
id: this.ids,
label: this.labels
}
// 数据改变将改变后的数据传给父组件处理
this.$emit('changeLabelCallback', params)
},
// 筛选事件
filterNode(value, data) {
if (!value) return true
return data.labelName.indexOf(value) !== -1
},
// 获取数据源
getData() {
queryBusiLevelLabelApi({ labelType: '业务标签' }).then((res) => {
if (res.success) {
this.queryData = res.object;
}
});
},
handdleRemoveTag(e) {
console.log(e, this.labels);
let code = ''
this.queryData.forEach((i, idx) => {
if (e == i.labelName) {
code = i.labelId;
} else {
i.childernLabel.forEach((ii) => {
if (e == ii.labelName) {
code = ii.labelId;
}
});
}
});
let leng = this.ids.indexOf(code)
this.ids.splice(leng, 1);
const arrs = []
this.ids.forEach((it, index) => {
arrs.push({
labelId: it,
labelName: this.labels[index]
})
})
this.$refs.trees.setCheckedNodes(arrs)
},
}
}
</script>
<style lang="scss" scoped></style>
7.父组件引用
<tree-select2 :busilabel="formState.busiLevelLabelList"
:filterable="false"
:allowcreate="false"
@changeLabelCallback="changeLabel"></tree-select2>
``````引入
import treeSelect2 from '@/components/treeselect2.vue'
``````注册
components: { treeSelect2 },
``````
// 需要回显的数据集合
id: [],
label: [],
``````
// 接收treeselect2返回的数据
changeLabel(val) {
console.log(val)
}
记录开发日常,如有不足还望指出,感谢!