当前位置:   article > 正文

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

element树形下拉框

目录

简述

效果

功能描述

代码实现

总结


简述

基于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="filterableFor || remoteFor"
  14. :remote="filterableFor || remoteFor"
  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. filterable: {
  58. type: Boolean,
  59. default: false
  60. },
  61. // 是否远程搜索,要设置远程搜索方法
  62. remote: {
  63. type: Boolean,
  64. default: false
  65. },
  66. // 远程方法
  67. remoteMethod: {
  68. type: Function
  69. },
  70. treeOptions: {
  71. type: Array,
  72. default: () => {
  73. return []
  74. }
  75. },
  76. defaultProps: {
  77. type: Object,
  78. default: () => {
  79. return {
  80. children: 'children',
  81. label: 'label',
  82. value: 'value'
  83. }
  84. }
  85. }
  86. },
  87. watch: {
  88. treeOptions: {
  89. handler(newValue) {
  90. this.loading = false
  91. this.dataOfTree = JSON.parse(JSON.stringify(newValue))
  92. // 保留源数据;
  93. this.dataSource = JSON.parse(JSON.stringify(newValue))
  94. },
  95. deep: true,
  96. immediate: false
  97. },
  98. defaultValue: {
  99. handler(newValue) {
  100. this.selectedNode = {}
  101. this.currentLabel = undefined
  102. this.currentValue = newValue
  103. this.$nextTick(() => {
  104. // 过滤方式是通过value还是label;
  105. this.isFilterWithValue = true
  106. if (this.dataOfTree) {
  107. this.$refs.treeRef.filter(newValue)
  108. }
  109. })
  110. },
  111. deep: true,
  112. immediate: true
  113. }
  114. },
  115. computed: {
  116. // 是否支持搜索,本地搜索,与远程搜索配置互斥。
  117. filterableFor() {
  118. return this.remote ? false : this.filterable
  119. },
  120. remoteFor() {
  121. return this.filterable ? false : this.remote
  122. }
  123. },
  124. data() {
  125. return {
  126. selectedNode: {},
  127. loading: false,
  128. currentValue: undefined,
  129. currentLabel: undefined,
  130. dataOfTree: []
  131. }
  132. },
  133. created() {
  134. this.dataOfTree = JSON.parse(JSON.stringify(this.treeOptions))
  135. // 保留源数据;
  136. this.dataSource = JSON.parse(JSON.stringify(this.treeOptions))
  137. },
  138. mounted() {
  139. },
  140. methods: {
  141. selectRemoteMethod(val) {
  142. this.isFilterWithValue = false
  143. if (this.filterableFor) {
  144. // 本地过滤
  145. this.$refs.treeRef.filter(val)
  146. } else if (this.remoteFor) {
  147. // 远程搜索
  148. this.loading = true
  149. this.remoteMethod(val)
  150. }
  151. },
  152. handleClear() {
  153. // 如果内容被清空
  154. this.selectedNode = {}
  155. this.currentLabel = undefined
  156. this.currentValue = undefined
  157. const result = this.buildEmptyResult()
  158. this.$emit('myInputEvent', result)
  159. this.$emit('onNodeSelectEvent', result)
  160. },
  161. handleVisibleChange(visible) {
  162. if (!visible) {
  163. // 先移除所有数据;
  164. this.dataOfTree.splice(0)
  165. // 恢复原来的所有数据;
  166. this.dataOfTree.splice(0, 0, ...this.dataSource)
  167. // 本地过滤
  168. this.$refs.treeRef.filter('')
  169. }
  170. },
  171. filterNode(value, data) {
  172. if (!value) {
  173. return data
  174. }
  175. if (this.isFilterWithValue) {
  176. if (data[this.defaultProps.value] === value) {
  177. this.selectedNode = data
  178. this.currentLabel = data[this.defaultProps.label]
  179. this.$refs.treeRef.setCurrentKey(this.selectedNode[this.defaultProps.value])
  180. const result = this.buildResultByNodeData(data)
  181. this.$emit('myInputEvent', result)
  182. }
  183. } else {
  184. return data[this.defaultProps.label].indexOf(value) !== -1
  185. }
  186. return data
  187. },
  188. closeSelect() {
  189. this.$refs.selectRef.blur()
  190. },
  191. /**
  192. * @param data
  193. * @param node
  194. * @param comp
  195. */
  196. handleNodeClicked(data, node, comp) {
  197. this.selectedNode = data
  198. this.currentLabel = data[this.defaultProps.label]
  199. this.currentValue = data[this.defaultProps.value]
  200. const result = this.buildResultByNodeData(data)
  201. this.$emit('myInputEvent', result)
  202. this.$emit('onNodeSelectEvent', result)
  203. this.closeSelect()
  204. },
  205. buildResultByNodeData(data) {
  206. return {
  207. node: data[this.defaultProps.value],
  208. data: {
  209. label: data[this.defaultProps.label],
  210. value: data[this.defaultProps.value]
  211. },
  212. meta: data
  213. }
  214. },
  215. buildEmptyResult() {
  216. return {
  217. node: undefined,
  218. data: {
  219. label: undefined,
  220. value: undefined
  221. },
  222. meta: undefined
  223. }
  224. }
  225. }
  226. }
  227. </script>
  228. <style lang='scss' scoped>
  229. </style>

应用示例1:

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

 应用示例2:

  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. remote
  15. :remote-method="handleRemote"
  16. :tree-options="treeOptions"
  17. :default-value="form.tree.node"
  18. @onNodeSelectEvent="handleNodeSelectEvent($event)"
  19. />
  20. </el-form-item>
  21. </el-form>
  22. <div>
  23. <el-button @click="reset">重置</el-button>
  24. <el-button @click="submit">提交</el-button>
  25. </div>
  26. </div>
  27. </template>
  28. <script>
  29. import {Message} from 'element-ui'
  30. import SelectTree from '@/views/components/SelectTree.vue'
  31. export default {
  32. name: 'SelectTreeExample',
  33. components: {
  34. SelectTree
  35. },
  36. props: {},
  37. data() {
  38. return {
  39. form: {
  40. tree: {node: undefined, data: {}}
  41. },
  42. treeOptions: [{
  43. value: 1,
  44. label: '一级 1',
  45. children: [{
  46. value: 11,
  47. label: '二级 1-1',
  48. children: [{
  49. value: 111,
  50. label: '三级 1-1-1'
  51. }]
  52. }]
  53. }, {
  54. value: 2,
  55. label: '一级 2',
  56. children: [{
  57. value: 21,
  58. label: '二级 2-1'
  59. }]
  60. }, {
  61. value: 3,
  62. label: '一级 3',
  63. children: [{
  64. value: 31,
  65. label: '二级 3-1',
  66. children: [{
  67. value: 311,
  68. label: '三级 3-1-1'
  69. }]
  70. }, {
  71. value: 32,
  72. label: '二级 3-2',
  73. children: [{
  74. value: 321,
  75. label: '三级 3-2-1'
  76. }]
  77. }]
  78. }]
  79. }
  80. },
  81. mounted() {
  82. // 模拟接口请求,反显选择数据
  83. setTimeout(() => {
  84. this.form.tree.node = 2
  85. }, 1000)
  86. },
  87. methods: {
  88. reset() {
  89. this.form.tree = {node: undefined, data: {}}
  90. },
  91. submit() {
  92. const data = this.form.tree.data
  93. Message.info(`选中节点名称是${data.label},值是${data.value}`)
  94. },
  95. handleRemote() {
  96. setTimeout(() => {
  97. this.treeOptions = [{
  98. value: 1,
  99. label: '一级 1',
  100. children: [{
  101. value: 11,
  102. label: '二级 1-1',
  103. children: [{
  104. value: 111,
  105. label: '三级 1-1-1'
  106. }]
  107. }]
  108. }]
  109. }, 3000)
  110. },
  111. handleNodeSelectEvent(dataSelected) {
  112. }
  113. }
  114. }
  115. </script>
  116. <style lang='scss' scoped>
  117. </style>

总结

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

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

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

闽ICP备14008679号