组件页面代码(新增multiple 多选模式默认 false)
<template>
<el-select
:title="multiple? optionData.name : ''"
ref="select"
:value="value"
placeholder="请选择"
size="mini"
clearable
:disabled="disabled"
:filterable="filterable"
:filter-method="filterMethod"
style="width: 100%;"
@clear="clear"
@visible-change="visibleChange"
>
<el-option
ref="option"
class="tree-select__option"
:value="optionData.id"
:label="optionData.name"
>
<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"
:filter-node-method="filterNode"
@node-click="handleNodeClick"
@check-change="handleCheckChange"
></el-tree>
</el-option>
</el-select>
</template>
<script>
export default {
name: 'TreeSelect',
props: {
// v-model绑定
value: {
type: [String, Number],
default: ''
},
multiple: {
type: Boolean,
default: true //单项 false 多选true
},
// 树形的数据
data: {
type: Array,
default: function () {
return []
}
},
// 每个树节点用来作为唯一标识的属性
nodeKey: {
type: [String, Number],
default: 'id'
},
filterable: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
// tree的props配置
props: {
type: Object,
default: function () {
return {
label: 'label',
children: 'children'
}
}
}
},
data() {
return {
optionData: {
id: '',
name: ''
},
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) {
if (this.multiple) {
return
}
this.$emit('input', data[this.nodeKey])
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.name = 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 || 'name'
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="scss">
.tree-select__option {
&.el-select-dropdown__item {
height: auto;
line-height: 1;
padding: 0;
background-color: #fff;
}
}
.tree-select__tree {
padding: 4px 20px;
font-weight: 400;
&.tree-select__tree--radio {
.el-tree-node.is-current > .el-tree-node__content {
color: $mainColor;
font-weight: 700;
}
}
}
</style>
vue 页面引用
<template>
<div class="container">
<cy-tree-select v-model="value" filterable :data="list" ref="tselect"></cy-tree-select>
</div>
</template>
<script>
import cyTreeSelect from '../components/treeSelect/index'
export default {
data() {
return {
list: [{
label: '系统',
id: 1,
children: [
{ label: '用户', id: 2 },
{ label: '用户组', id: 3 },
{ label: '角色', id: 4 },
{ label: '菜单', id: 5 },
{ label: '组织架构', id: 6 }
]
},
{
label: '商品',
id: 7,
children: [
{ label: '列表', id: 8 },
{ label: '添加', id: 9 },
{ label: '修改', id: 10 },
{ label: '删除', id: 11 },
{ label: '商品分类', id: 12 },
{ label: '分类修改', id: 13 }
]
}],
value: 1 //多选时获取的是label,单选时获取的是id
}
}
}
//let s = this.$refs.tselect.optionData
// console.log(s) //数据拿取 optionData: {id: '',name: ''}格式
</script>
转载于https://zhuanlan.zhihu.com/p/415995268,供学习