使用效果图:
SelectTree组件
<template>
<el-select
:title="multiple ? optionData.label : ''"
ref="select"
:value="value"
placeholder="请选择"
:size="size"
:clearable="clearable"
:disabled="disabled"
:filterable="filterable"
:filter-method="filterMethod"
style="width: 100%;"
@clear="clear"
@visible-change="visibleChange"
>
<el-option
ref="option"
hidden
class="tree-select__option"
:value="optionData.id"
:label="optionData.label"
>
</el-option>
<el-tree
ref="tree"
class="tree-select__tree"
:class="`tree-select__tree--${multiple ? 'checked' : 'radio'}`"
:node-key="nodeKey"
:data="data"
:props="props"
:default-expanded-keys="[value]"
:show-checkbox="multiple"
:highlight-current="!multiple"
:expand-on-click-node="multiple"
:default-expand-all="expand"
:filter-node-method="filterNode"
@node-click="handleNodeClick"
@check-change="handleCheckChange"
></el-tree>
</el-select>
</template>
<script>
export default {
name: "TreeSelect",
props: {
size: {
type: String,
default: "small"
},
// v-model绑定
value: {
type: [String, Number],
default: ""
},
multiple: {
type: Boolean,
default: false
},
clearable: {
type: Boolean,
default: false
},
// 树形的数据
data: {
type: Array,
default: function() {
return [];
}
},
// 每个树节点用来作为唯一标识的属性
nodeKey: {
type: [String, Number],
default: "id"
},
filterable: {
type: Boolean,
default: false
},
expand: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
// tree的props配置
props: {
type: Object,
default: function() {
return {
label: "label",
children: "children"
};
}
},
// 父节点是否可选
parentSelectable: {
type: Boolean,
default: true
}
},
data() {
return {
optionData: {
id: "",
label: ""
},
filterFlag: false
};
},
watch: {
value: {
handler(val) {
if (!this.isEmpty(this.data)) {
this.init(val);
}
},
immediate: true
},
data: function(val) {
if (!this.isEmpty(val)) {
this.init(this.value);
}
}
},
created() {},
methods: {
// 是否为空
isEmpty(val) {
for (let key in val) {
return false;
}
return true;
},
handleNodeClick(data, node) {
if (this.multiple) {
return;
}
if (!this.parentSelectable) {
this.$refs.tree.setCurrentKey(data.id);
if (data.children && data.children.length) {
return;
}
}
this.$emit("input", data[this.nodeKey]);
this.$emit("select", data, node);
this.$refs.select.visible = false;
},
handleCheckChange() {
const nodes = this.$refs.tree.getCheckedNodes();
const value = nodes.map(item => item[this.nodeKey]).join(",");
this.$emit("input", value);
},
init(val) {
// 多选
if (this.multiple) {
const arr = val.toString().split(",");
this.$nextTick(() => {
this.$refs.tree.setCheckedKeys(arr);
const nodes = this.$refs.tree.getCheckedNodes();
this.optionData.id = val;
this.optionData.label = nodes
.map(item => item[this.props.label])
.join(",");
});
}
// 单选
else {
val = val === "" ? null : val;
this.$nextTick(() => {
this.$refs.tree.setCurrentKey(val);
if (val === null) {
return;
}
const label = this.props.label || "label";
const node = this.$refs.tree.getNode(val);
this.optionData.id = val;
this.optionData[label] = node.label;
});
}
},
visibleChange(e) {
if (e) {
const tree = this.$refs.tree;
this.filterFlag && tree.filter("");
this.filterFlag = false;
let selectDom = null;
if (this.multiple) {
selectDom = tree.$el.querySelector(".el-tree-node.is-checked");
} else {
selectDom = tree.$el.querySelector(".is-current");
}
setTimeout(() => {
this.$refs.select.scrollToOption({ $el: selectDom });
}, 0);
}
},
clear() {
this.$emit("input", "");
},
filterMethod(val) {
this.filterFlag = true;
this.$refs.tree.filter(val);
},
filterNode(value, data) {
if (!value) return true;
const label = this.props.label || "name";
return data[label].indexOf(value) !== -1;
}
}
};
</script>
<style lang="less">
.tree-select__option {
&.el-select-dropdown__item {
height: auto;
line-height: 1;
padding: 0;
}
}
.tree-select__tree {
font-weight: 400;
&.tree-select__tree--radio {
.el-tree-node.is-current > .el-tree-node__content {
background-color: #1263dd !important;
color: #fff !important;
font-weight: bold;
}
.el-tree-node__content:hover {
background-color: #0f428f;
color: #fff;
}
}
}
</style>
父组件中引用:
//父组件中
<el-table ref="table" :data="tableData" border stripe height="100%">
<el-table-column
label="指标"
prop="indicatorName"
min-width="150"
>
<template slot-scope="scope">
<span v-if="scope.row.indicatorName.length">{{
scope.row.indicatorName
}}</span>
//使用子组件
<SelectTree
v-else
size="mini"
:data="indicatorNameList"
expand
v-model="scope.row.indicatorName"
:parentSelectable="false"
filterable
@select="handleNameNodeClick(scope.$index, ...arguments)"
/>
</template>
</el-table-column>
</el-table>
//引用和注册子组件
import SelectTree from "./components/SelectTreeNew";//路径写在哪就在哪引用
export default {
components: { SelectTree },
//在data中声明要用的参数
data(){
return{
tableData:[],
indicatorNameList:[],//下拉树的数据
}
}
}
//methods中处理下拉树的点击事件
methods:{
handleNameNodeClick(index, data, node) {
//点击与树节点相关数据都在index data node,按照需求获取即可
},
//获取下拉树的数据,给indicatorNamrList赋值
getIndicatorNameList() {
setTimeout(() => {
//假数据 实际接口获取
let indicatorTree = [
{
id: "baseInfo",
label: "基本信息",
parentId: null,
leaf: false,
checked: false,
address: null,
children: [
{
id: "code",
label: "基本信息响应码",
parentId: null,
leaf: true,
checked: false,
address: null,
children: null,
alarmCount: 0,
hasSerious: false,
hasWarn: false,
hasCommonly: false,
hasRemind: false
},
{
id: "collefctTime",
label: "基本信息时间",
parentId: null,
leaf: true,
checked: false,
address: null,
children: null,
alarmCount: 0,
hasSerious: false,
hasWarn: false,
hasCommonly: false,
hasRemind: false
},
{
id: "gldrervw",
label: "管理单位",
parentId: null,
leaf: true,
checked: false,
address: null,
children: null,
alarmCount: 0,
hasSerious: false,
hasWarn: false,
hasCommonly: false,
hasRemind: false
},
{
id: "intSet",
label: "智能能力集",
parentId: null,
leaf: true,
checked: false,
address: null,
children: null,
alarmCount: 0,
hasSerious: false,
hasWarn: false,
hasCommonly: false,
hasRemind: false
},
{
id: "Classification",
label: "设施分类",
parentId: null,
leaf: true,
checked: false,
address: null,
children: null,
alarmCount: 0,
hasSerious: false,
hasWarn: false,
hasCommonly: false,
hasRemind: false
},
{
id: "type",
label: "功能类型",
parentId: null,
leaf: true,
checked: false,
address: null,
children: null,
alarmCount: 0,
hasSerious: false,
hasWarn: false,
hasCommonly: false,
hasRemind: false
},
{
id: "installTime",
label: "安装时间",
parentId: null,
leaf: true,
checked: false,
address: null,
children: null,
alarmCount: 0,
hasSerious: false,
hasWarn: false,
hasCommonly: false,
hasRemind: false
},
{
id: "exTime",
label: "到期时间",
parentId: null,
leaf: true,
checked: false,
address: null,
children: null,
alarmCount: 0,
hasSerious: false,
hasWarn: false,
hasCommonly: false,
hasRemind: false
},
{
id: "fdsgh",
label: "摄像机采集区域",
parentId: null,
leaf: true,
checked: false,
address: null,
children: null,
alarmCount: 0,
hasSerious: false,
hasWarn: false,
hasCommonly: false,
hasRemind: false
}
]
}
];
//将获取的数据进行转换
this.indicatorNameList = JSON.parse(JSON.stringify(indicatorTree));
this.indicatorNameList.forEach(item => {
item.selectable = false;
});
}, 100);
},
}