使用组件:Popover 弹出框、Tree 树形控件 和 input 输入框
用法:
1、新建一个.vue文件,粘贴以下组件封装的代码(完全可以使用)
2、在页面需要使用下拉树的地方调用即可。
(1)import selectTree from '@/components/selectTree/selectTree'
(2)components: {selectTree}
(3)页面调用
组件封装代码:
1 <template> 2 <div v-if="update"> 3 <el-popover 4 popper-class="selectTree" 5 placement="bottom-start" 6 transition="fade-in-linear" 7 v-model="visible" 8 min-width="200" 9 trigger="click"> 10 <el-tree 11 :data="data" 12 :props="defaultProps" 13 empty-text="无数据" 14 :node-key="defaultProps.id" 15 :default-expanded-keys="defaultExpandedKeys" 16 :check-on-click-node="true" 17 ref="tree1" 18 :expand-on-click-node="false" 19 :filter-node-method="filterNode" 20 :highlight-current="true" 21 @node-click="handleNodeClick"> 22 el-tree> 23 <el-input 24 v-model="filterText" 25 @clear="clear" 26 :placeholder="placeholder" 27 :disabled="disabled" 28 slot="reference" 29 :clearable="clearable" 30 :suffix-icon="icon"> 31 el-input> 32 el-popover> 33 div> 34 template> 35 <script> 36 export default { 37 name: 'selectTree', 38 props: { 39 value: String, 40 data: Array, 41 placeholder: { 42 type: String, 43 default: '请选择' 44 }, 45 disabled: { 46 type: Boolean, 47 default: false, 48 }, 49 clearable: { 50 type: Boolean, 51 default: true, 52 }, 53 filterable: { //禁选值 54 type: String, 55 default: undefined, 56 }, 57 defaultProps: { 58 type: Object, 59 default() { 60 return { 61 children: 'children', 62 label: 'label', 63 id: 'id', 64 } 65 } 66 }, 67 nodeKey: { 68 type: String, 69 default: 'id', 70 } 71 }, 72 data() { 73 return { 74 defaultExpandedKeys: ['-1'], //默认展开 75 filterText: '', 76 visible: false, 77 icon: 'el-icon-arrow-down', 78 update: true, 79 } 80 }, 81 async created() { 82 if (this.filterable) { 83 this.setFilter(this.data) 84 } 85 }, 86 mounted() { 87 this.setFilterText() 88 }, 89 watch: { 90 value(val) { 91 if (!val) { //没有值得时候 92 this.filterText = '' 93 } else { 94 if (this.$refs.tree1) { 95 this.$refs.tree1.setCurrentKey(val) 96 let obj = this.$refs.tree1.getCurrentNode() 97 if (obj) { 98 this.filterText = obj[this.defaultProps.label] 99 return 100 } else { 101 let tree = this.$refs.tree1 102 this.$nextTick(() => { 103 tree.setCurrentKey(val) 104 let obj = tree.getCurrentNode() 105 if (obj) { 106 this.filterText = obj[this.defaultProps.label] 107 } 108 return 109 }) 110 } 111 } 112 } 113 }, 114 visible(val) { 115 if (val === true) { 116 this.icon = "el-icon-arrow-up" 117 } else { 118 this.icon = "el-icon-arrow-down" 119 } 120 }, 121 filterable(val) { 122 this.update = false 123 this.setFilter(this.data) 124 this.$nextTick(() => { 125 this.update = true 126 }) 127 } 128 }, 129 methods: { 130 setFilterText() { 131 if (!this.value) { 132 return 133 } else { 134 this.$refs.tree1.setCurrentKey(this.value) 135 let obj = this.$refs.tree1.getCurrentNode() 136 if (obj) { 137 this.filterText = obj[this.defaultProps.label] 138 } 139 } 140 }, 141 setFilter(arr) { 142 arr.map(item => { 143 if (item.id === this.filterable) { 144 item.disabled = true 145 if (item.children && item.children.length != 0) { 146 this.setDisabled(item.children) 147 } 148 } else { 149 item.disabled = false 150 if (item.children && item.children.length != 0) { 151 this.setFilter(item.children) 152 } 153 154 } 155 }) 156 }, 157 setDisabled(arr) { 158 arr.map(item => { 159 item.disabled = true 160 if (item.children && item.children.length != 0) { 161 this.setDisabled(item.children) 162 } 163 }) 164 165 }, 166 filterNode(value, data) { 167 if (!value) return true; 168 return data.label.indexOf(value) !== -1; 169 }, 170 handleNodeClick(obj, node) { 171 if (node.data.disabled === true || this.disabled === true) { 172 return 173 } 174 this.$refs.tree1.setCurrentKey(obj[this.defaultProps.id]) 175 this.$emit('input', obj[this.defaultProps.id]) 176 this.filterText = obj[this.defaultProps.label] 177 this.visible = false 178 }, 179 clear() { 180 this.$refs.tree1.setCurrentKey('') 181 this.$emit('input', '') 182 } 183 }, 184 beforeDestroy() { 185 }, 186 destroyed() { 187 } 188 } 189 190 script> 191 <style lang="scss"> 192 .selectTree { 193 max-height: 600px; 194 overflow-y: auto; 195 overflow-x: hidden; 196 197 div[aria-disabled="true"] { 198 .el-tree-node__content { 199 cursor: not-allowed; 200 } 201 } 202 } 203 204 style>
组件封装代码
1 <selectTree 2 :data="treeDataSelect" 3 :defaultProps="{children:'children',label:'name',id:'id'}" 4 :filterable="addDirForm.id" 5 v-model="addDirForm.parentId"> 6 selectTree>
其中treeDataSelect的数据格式如下所示:
1 [ 2 { 3 "id":"527AF5EB3A6A463294181DBE13E36CD7", 4 "parentId":"-1", 5 "dirType":0, 6 "dirName":"test", 7 "children":[ 8 { 9 "id":"434051D4A7F5459FADCEC3A3BE79F83F", 10 "parentId":"527AF5EB3A6A463294181DBE13E36CD7", 11 "dirType":0, 12 "dirName":"testChild", 13 "children":null, 14 "label":null, 15 "name":"testChild" 16 } 17 ], 18 "label":null, 19 "name":"test" 20 } 21 ]
效果截图