当前位置:   article > 正文

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

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

目录

简述

效果

功能描述

代码实现

总结


简述

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

效果

先看效果:

下拉状态:

选择后状态:

选择的数据:

功能描述

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

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

3、高亮选择行; 

4、设置默认选择行; 

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

代码实现

树状下拉组件代码:

  1. <!--
  2. 树状下拉选择框:
  3. 1、加载树结构,实现树状下拉选择组件;
  4. 2、可通过关键词实现本地和远程过滤;
  5. 3、高亮选择行;
  6. 4、设置默认选择行;
  7. 5、可直接应用在form表单;
  8. -->
  9. <template>
  10. <el-select
  11. ref="selectRef"
  12. clearable
  13. filterable
  14. :remote="remote"
  15. :remote-method="selectRemoteMethod"
  16. v-model="currentLabel"
  17. @visible-change="handleVisibleChange"
  18. @clear="handleClear"
  19. >
  20. <el-option
  21. style="height: 100%; padding: 0"
  22. value=""
  23. v-loading="loading"
  24. element-loading-text="加载中..."
  25. element-loading-spinner="el-icon-loading"
  26. >
  27. <el-tree
  28. ref="treeRef"
  29. :data="dataOfTree"
  30. :node-key="defaultProps.value"
  31. :props="defaultProps"
  32. highlight-current
  33. default-expand-all
  34. :current-node-key="selectedNode.value"
  35. :expand-on-click-node="false"
  36. @node-click="handleNodeClicked"
  37. :filter-node-method="filterNode"
  38. >
  39. </el-tree>
  40. </el-option>
  41. </el-select>
  42. </template>
  43. <script>
  44. export default {
  45. name: 'SelectTree',
  46. components: {},
  47. model: {
  48. prop: 'inputValue',
  49. event: 'myInputEvent'
  50. },
  51. props: {
  52. // 默认选中值
  53. defaultValue: {
  54. type: Number
  55. },
  56. // 是否远程搜索
  57. remote: {
  58. type: Boolean,
  59. default: false
  60. },
  61. // 远程方法
  62. remoteMethod: {
  63. type: Function
  64. },
  65. treeOptions: {
  66. type: Array,
  67. default: () => {
  68. return []
  69. }
  70. },
  71. defaultProps: {
  72. type: Object,
  73. default: () => {
  74. return {
  75. children: 'children',
  76. label: 'label',
  77. value: 'value'
  78. }
  79. }
  80. }
  81. },
  82. watch: {
  83. treeOptions: {
  84. handler(newValue) {
  85. this.dataOfTree = JSON.parse(JSON.stringify(newValue))
  86. // 保留源数据;
  87. this.dataSource = JSON.parse(JSON.stringify(newValue))
  88. },
  89. deep: true,
  90. immediate: false
  91. },
  92. defaultValue: {
  93. handler(newValue) {
  94. this.selectedNode = {}
  95. this.currentLabel = undefined
  96. this.currentValue = newValue
  97. this.$nextTick(() => {
  98. // 过滤方式是通过value还是label;
  99. this.isFilterWithValue = true
  100. if (this.dataOfTree) {
  101. this.$refs.treeRef.filter(newValue)
  102. }
  103. })
  104. },
  105. deep: true,
  106. immediate: true
  107. }
  108. },
  109. data() {
  110. return {
  111. selectedNode: {},
  112. loading: false,
  113. currentValue: undefined,
  114. currentLabel: undefined,
  115. dataOfTree: []
  116. }
  117. },
  118. created() {
  119. this.dataOfTree = JSON.parse(JSON.stringify(this.treeOptions))
  120. // 保留源数据;
  121. this.dataSource = JSON.parse(JSON.stringify(this.treeOptions))
  122. },
  123. mounted() {
  124. },
  125. methods: {
  126. selectRemoteMethod(val) {
  127. this.isFilterWithValue = false
  128. if (this.remote) {
  129. // 远程搜索
  130. this.remoteMethod(val)
  131. } else {
  132. // 本地过滤
  133. this.$refs.treeRef.filter(val)
  134. }
  135. },
  136. handleClear() {
  137. // 如果内容被清空
  138. this.selectedNode = {}
  139. this.currentLabel = undefined
  140. this.currentValue = undefined
  141. const result = this.buildEmptyResult()
  142. this.$emit('myInputEvent', result)
  143. this.$emit('onNodeSelectEvent', result)
  144. },
  145. handleVisibleChange(visible) {
  146. if (!visible) {
  147. // 先移除所有数据;
  148. this.dataOfTree.splice(0)
  149. // 恢复原来的所有数据;
  150. this.dataOfTree.splice(0, 0, ...this.dataSource)
  151. // 本地过滤
  152. this.$refs.treeRef.filter('')
  153. }
  154. },
  155. filterNode(value, data) {
  156. if (!value) {
  157. return data
  158. }
  159. if (this.isFilterWithValue) {
  160. if (data[this.defaultProps.value] === value) {
  161. this.selectedNode = data
  162. this.currentLabel = data[this.defaultProps.label]
  163. this.$refs.treeRef.setCurrentKey(this.selectedNode[this.defaultProps.value])
  164. const result = this.buildResultByNodeData(data)
  165. this.$emit('myInputEvent', result)
  166. }
  167. } else {
  168. return data[this.defaultProps.label].indexOf(value) !== -1
  169. }
  170. return data
  171. },
  172. closeSelect() {
  173. this.$refs.selectRef.blur()
  174. },
  175. /**
  176. * @param data
  177. * @param node
  178. * @param comp
  179. */
  180. handleNodeClicked(data, node, comp) {
  181. this.selectedNode = data
  182. this.currentLabel = data[this.defaultProps.label]
  183. this.currentValue = data[this.defaultProps.value]
  184. const result = this.buildResultByNodeData(data)
  185. this.$emit('myInputEvent', result)
  186. this.$emit('onNodeSelectEvent', result)
  187. this.closeSelect()
  188. },
  189. buildResultByNodeData(data) {
  190. return {
  191. node: data[this.defaultProps.value],
  192. data: {
  193. label: data[this.defaultProps.label],
  194. value: data[this.defaultProps.value]
  195. },
  196. meta: data
  197. }
  198. },
  199. buildEmptyResult() {
  200. return {
  201. node: undefined,
  202. data: {
  203. label: undefined,
  204. value: undefined
  205. },
  206. meta: undefined
  207. }
  208. }
  209. }
  210. }
  211. </script>
  212. <style lang='scss' scoped>
  213. </style>

应用示例:

  1. <template>
  2. <div>
  3. <div>测试表单</div>
  4. <el-form
  5. ref="demandFormRef"
  6. :model="form"
  7. label-suffix=":"
  8. status-icon
  9. label-position="left"
  10. >
  11. <el-form-item label="树" label-width="85px" prop="tree">
  12. <select-tree
  13. v-model="form.tree"
  14. :tree-options="treeOptions"
  15. :default-value="form.tree.node"
  16. @onNodeSelectEvent="handleNodeSelectEvent($event)"
  17. />
  18. </el-form-item>
  19. </el-form>
  20. <div>
  21. <el-button @click="reset">重置</el-button>
  22. <el-button @click="submit">提交</el-button>
  23. </div>
  24. </div>
  25. </template>
  26. <script>
  27. import {Message} from 'element-ui'
  28. import SelectTree from '@/components/SelectTree/index'
  29. export default {
  30. components: {
  31. SelectTree
  32. },
  33. props: {},
  34. data() {
  35. return {
  36. form: {
  37. tree: {node: undefined, data: {}}
  38. },
  39. treeOptions: [{
  40. value: 1,
  41. label: '一级 1',
  42. children: [{
  43. value: 11,
  44. label: '二级 1-1',
  45. children: [{
  46. value: 111,
  47. label: '三级 1-1-1'
  48. }]
  49. }]
  50. }, {
  51. value: 2,
  52. label: '一级 2',
  53. children: [{
  54. value: 21,
  55. label: '二级 2-1'
  56. }]
  57. }, {
  58. value: 3,
  59. label: '一级 3',
  60. children: [{
  61. value: 31,
  62. label: '二级 3-1',
  63. children: [{
  64. value: 311,
  65. label: '三级 3-1-1'
  66. }]
  67. }, {
  68. value: 32,
  69. label: '二级 3-2',
  70. children: [{
  71. value: 321,
  72. label: '三级 3-2-1'
  73. }]
  74. }]
  75. }]
  76. }
  77. },
  78. mounted() {
  79. // 模拟接口请求,反显选择数据
  80. // setTimeout(() => {
  81. // this.form.tree.node = 2
  82. // }, 1000)
  83. },
  84. methods: {
  85. reset() {
  86. this.form.tree = {node: undefined, data: {}}
  87. },
  88. submit() {
  89. const data = this.form.tree.data
  90. Message.info(`选中节点名称是${data.label},值是${data.value}`)
  91. },
  92. handleNodeSelectEvent(dataSelected){
  93. }
  94. }
  95. }
  96. </script>
  97. <style lang='scss' scoped>
  98. </style>

总结

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/901100
推荐阅读
相关标签
  

闽ICP备14008679号