目录
简述
效果
功能描述
代码实现
总结
简述
基于Element UI内置的Select下拉和Tree树形组件,组合封装的树状下拉选择器。
效果
先看效果:
下拉状态:
选择后状态:
选择的数据:
功能描述
1、加载树结构,实现树状下拉选择器;
2、可通过关键词实现本地和远程过滤;
3、高亮选择行;
4、设置默认选择行;
5、可直接应用在form表单;
代码实现
树状下拉组件代码:
<!--树状下拉选择框:1、加载树结构,实现树状下拉选择组件;2、可通过关键词实现本地和远程过滤;3、高亮选择行;4、设置默认选择行;5、可直接应用在form表单;
-->
<template><el-selectref="selectRef"clearablefilterable:remote="remote":remote-method="selectRemoteMethod"v-model="currentLabel"@visible-change="handleVisibleChange"@clear="handleClear"><el-optionstyle="height: 100%; padding: 0"value=""v-loading="loading"element-loading-text="加载中..."element-loading-spinner="el-icon-loading"><el-treeref="treeRef":data="dataOfTree":node-key="defaultProps.value":props="defaultProps"highlight-currentdefault-expand-all:current-node-key="selectedNode.value":expand-on-click-node="false"@node-click="handleNodeClicked":filter-node-method="filterNode"></el-tree></el-option></el-select>
</template>
<script>export default {name: 'SelectTree',components: {},model: {prop: 'inputValue',event: 'myInputEvent'},props: {// 默认选中值defaultValue: {type: Number},// 是否远程搜索remote: {type: Boolean,default: false},// 远程方法remoteMethod: {type: Function},treeOptions: {type: Array,default: () => {return []}},defaultProps: {type: Object,default: () => {return {children: 'children',label: 'label',value: 'value'}}}},watch: {treeOptions: {handler(newValue) {this.dataOfTree = JSON.parse(JSON.stringify(newValue))// 保留源数据;this.dataSource = JSON.parse(JSON.stringify(newValue))},deep: true,immediate: false},defaultValue: {handler(newValue) {this.selectedNode = {}this.currentLabel = undefinedthis.currentValue = newValuethis.$nextTick(() => {// 过滤方式是通过value还是label;this.isFilterWithValue = trueif (this.dataOfTree) {this.$refs.treeRef.filter(newValue)}})},deep: true,immediate: true}},data() {return {selectedNode: {},loading: false,currentValue: undefined,currentLabel: undefined,dataOfTree: []}},created() {this.dataOfTree = JSON.parse(JSON.stringify(this.treeOptions))// 保留源数据;this.dataSource = JSON.parse(JSON.stringify(this.treeOptions))},mounted() {},methods: {selectRemoteMethod(val) {this.isFilterWithValue = falseif (this.remote) {// 远程搜索this.remoteMethod(val)} else {// 本地过滤this.$refs.treeRef.filter(val)}},handleClear() {// 如果内容被清空this.selectedNode = {}this.currentLabel = undefinedthis.currentValue = undefinedconst result = this.buildEmptyResult()this.$emit('myInputEvent', result)this.$emit('onNodeSelectEvent', result)},handleVisibleChange(visible) {if (!visible) {// 先移除所有数据;this.dataOfTree.splice(0)// 恢复原来的所有数据;this.dataOfTree.splice(0, 0, ...this.dataSource)// 本地过滤this.$refs.treeRef.filter('')}},filterNode(value, data) {if (!value) {return data}if (this.isFilterWithValue) {if (data[this.defaultProps.value] === value) {this.selectedNode = datathis.currentLabel = data[this.defaultProps.label]this.$refs.treeRef.setCurrentKey(this.selectedNode[this.defaultProps.value])const result = this.buildResultByNodeData(data)this.$emit('myInputEvent', result)}} else {return data[this.defaultProps.label].indexOf(value) !== -1}return data},closeSelect() {this.$refs.selectRef.blur()},/*** @param data* @param node* @param comp*/handleNodeClicked(data, node, comp) {this.selectedNode = datathis.currentLabel = data[this.defaultProps.label]this.currentValue = data[this.defaultProps.value]const result = this.buildResultByNodeData(data)this.$emit('myInputEvent', result)this.$emit('onNodeSelectEvent', result)this.closeSelect()},buildResultByNodeData(data) {return {node: data[this.defaultProps.value],data: {label: data[this.defaultProps.label],value: data[this.defaultProps.value]},meta: data}},buildEmptyResult() {return {node: undefined,data: {label: undefined,value: undefined},meta: undefined}}}
}
</script><style lang='scss' scoped>
</style>
应用示例:
<template><div><div>测试表单</div><el-formref="demandFormRef":model="form"label-suffix=":"status-iconlabel-position="left"><el-form-item label="树" label-width="85px" prop="tree"><select-treev-model="form.tree":tree-options="treeOptions":default-value="form.tree.node"@onNodeSelectEvent="handleNodeSelectEvent($event)"/></el-form-item></el-form><div><el-button @click="reset">重置</el-button><el-button @click="submit">提交</el-button></div></div>
</template>
<script>
import {Message} from 'element-ui'
import SelectTree from '@/components/SelectTree/index'export default {components: {SelectTree},props: {},data() {return {form: {tree: {node: undefined, data: {}}},treeOptions: [{value: 1,label: '一级 1',children: [{value: 11,label: '二级 1-1',children: [{value: 111,label: '三级 1-1-1'}]}]}, {value: 2,label: '一级 2',children: [{value: 21,label: '二级 2-1'}]}, {value: 3,label: '一级 3',children: [{value: 31,label: '二级 3-1',children: [{value: 311,label: '三级 3-1-1'}]}, {value: 32,label: '二级 3-2',children: [{value: 321,label: '三级 3-2-1'}]}]}]}},mounted() {// 模拟接口请求,反显选择数据// setTimeout(() => {// this.form.tree.node = 2// }, 1000)},methods: {reset() {this.form.tree = {node: undefined, data: {}}},submit() {const data = this.form.tree.dataMessage.info(`选中节点名称是${data.label},值是${data.value}`)},handleNodeSelectEvent(dataSelected){}}
}
</script><style lang='scss' scoped>
</style>
总结
本示例中,部分实现细节或者写法,可根据实际需要调整,树状下拉的实现方式有多种,这只是其中一种,只要符合实际需求就可以。
如果发现问题,欢迎随时提出,共同改进。