基于Element UI内置的Select下拉和Tree树形组件,组合封装的树状下拉选择器

avatar
作者
筋斗云
阅读量:0

目录

简述

效果

功能描述

代码实现

总结


简述

基于Element UI内置的Select下拉和Tree树形组件,组合封装的树状下拉选择器。

效果

先看效果:

下拉状态:

选择后状态:

选择的数据:

功能描述

1、加载树结构,实现树状下拉选择器; 

2、可通过关键词实现本地和远程过滤; 

3、高亮选择行; 

4、设置默认选择行; 

5、可直接应用在form表单;

代码实现

树状下拉组件代码:

<!--  树状下拉选择框:  1、加载树结构,实现树状下拉选择组件;  2、可通过关键词实现本地和远程过滤;  3、高亮选择行;  4、设置默认选择行;  5、可直接应用在form表单; --> <template>   <el-select       ref="selectRef"       clearable       filterable       :remote="remote"       :remote-method="selectRemoteMethod"       v-model="currentLabel"       @visible-change="handleVisibleChange"       @clear="handleClear"   >     <el-option         style="height: 100%; padding: 0"         value=""         v-loading="loading"         element-loading-text="加载中..."         element-loading-spinner="el-icon-loading"     >       <el-tree           ref="treeRef"           :data="dataOfTree"           :node-key="defaultProps.value"           :props="defaultProps"           highlight-current           default-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 = undefined         this.currentValue = newValue         this.$nextTick(() => {           // 过滤方式是通过value还是label;           this.isFilterWithValue = true           if (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 = false       if (this.remote) {         // 远程搜索         this.remoteMethod(val)       } else {         // 本地过滤         this.$refs.treeRef.filter(val)       }     },     handleClear() {       // 如果内容被清空       this.selectedNode = {}       this.currentLabel = undefined       this.currentValue = undefined       const 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 = data           this.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 = data       this.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-form         ref="demandFormRef"         :model="form"         label-suffix=":"         status-icon         label-position="left"     >       <el-form-item label="树" label-width="85px" prop="tree">         <select-tree             v-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.data       Message.info(`选中节点名称是${data.label},值是${data.value}`)     },     handleNodeSelectEvent(dataSelected){     }   } } </script>  <style lang='scss' scoped> </style> 

总结

本示例中,部分实现细节或者写法,可根据实际需要调整,树状下拉的实现方式有多种,这只是其中一种,只要符合实际需求就可以。

如果发现问题,欢迎随时提出,共同改进。

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!