当前位置:   article > 正文

vue3+element-puls 自定义TreeSelect 树形选择单选_element-plus tree勾选单选

element-plus tree勾选单选

 组件使用方式

<treeSelectRadio v-model="value" :options="options"></treeSelectRadio>

treeSelectRadio组件代码

  1. <template>
  2. <div class="tree_box">
  3. <el-select class="treeSelectRadio-select" v-model="select.value" clearable filterable ref="treeSelect"
  4. :placeholder="placeholder || '请选择'" :filter-method="selectFilter" @clear="clearAll">
  5. <el-option :value="select.currentNodeKey" :label="select.currentNodeLabel" class="treeSelectRadio-option-style"
  6. element-loading-background="rgba(255, 255, 255, 0.5)" v-loading="data.treeLoading"
  7. element-loading-text="loading">
  8. <el-scrollbar height="260px">
  9. <div class="check-box">
  10. <el-button text link :type="data.state === '' ? 'primary' : ''" :icon="Grid"
  11. @click.stop="handleState('')">全部</el-button>
  12. <el-button text link :type="data.state === 0 ? 'primary' : ''" :icon="Avatar"
  13. @click.stop="handleState(0)">在职</el-button>
  14. <el-button text link :type="data.state === 1 ? 'primary' : ''" :icon="Promotion"
  15. @click.stop="handleState(1)">离职</el-button>
  16. </div>
  17. <el-tree id="tree_v2" ref="treeRef" accordion :data="data.options" :props="props.TreeProps"
  18. :current-node-key="select.currentNodeKey" @node-click="nodeClick" :expand-on-click-node="false"
  19. :filter-node-method="treeFilter" node-key="id"></el-tree>
  20. </el-scrollbar>
  21. </el-option>
  22. </el-select>
  23. </div>
  24. </template>
  25. <script setup>
  26. import { nextTick, onMounted, reactive, ref, watch } from 'vue'
  27. import { Avatar, Promotion, Grid } from '@element-plus/icons-vue'
  28. import request from "@/utils/request"
  29. const props = defineProps({
  30. TreeProps: {
  31. type: Object,
  32. default() {
  33. return {
  34. value: 'id',
  35. label: 'name',
  36. children: 'children'
  37. }
  38. }
  39. },
  40. // 组件绑定的options
  41. options: {
  42. type: Array,
  43. default() {
  44. return []
  45. }
  46. },
  47. // 双向绑定值
  48. modelValue: {
  49. type: [String, Number],
  50. default: ''
  51. },
  52. // 空占位字符
  53. placeholder: {
  54. type: String,
  55. default: '请选择'
  56. }
  57. })
  58. const emits = defineEmits(['update:modelValue'])
  59. watch(() => props.options, (val) => {
  60. data.options = val
  61. setCurrent()
  62. })
  63. const select = reactive({
  64. value: props.modelValue.value,
  65. currentNodeKey: '',
  66. currentNodeLabel: ''
  67. })
  68. const data = reactive({
  69. treeLoading: false, // 加载loading~
  70. options: props.options, // 选项数组
  71. state: 0 // "" -- 全部 0 -- 在职 1 -- 离职
  72. })
  73. const treeSelect = ref(null)
  74. const nodeClick = (data, node) => {
  75. if(data.children && data.children.length > 0) {
  76. if(select.currentNodeKey){
  77. treeRef.value.setCurrentKey(select.currentNodeKey)
  78. }else{
  79. treeRef.value.setCurrentKey()
  80. }
  81. return
  82. }
  83. select.currentNodeKey = data[props.TreeProps.value]
  84. select.currentNodeLabel = data[props.TreeProps.label]
  85. select.value = data.id;
  86. treeSelect.value.blur()
  87. emits('update:modelValue', select.value)
  88. }
  89. // select 筛选方法 refs
  90. const treeRef = ref(null)
  91. const selectFilter = (query) => {
  92. treeRef.value.filter(query)
  93. }
  94. // 筛选方法
  95. const treeFilter = (value, dataValue) => {
  96. if (!value) return true
  97. return dataValue[props.TreeProps.label].toLowerCase().indexOf(value.toLowerCase()) !== -1
  98. }
  99. // 直接清空选择数据
  100. const clearAll = () => {
  101. select.currentNodeKey = ''
  102. select.currentNodeLabel = ''
  103. select.value = ''
  104. treeRef.value.setCurrentKey()
  105. emits('update:modelValue', '')
  106. }
  107. // setCurrent通过select.value 设置下拉选择tree 显示绑定的v-model值
  108. const setCurrent = () => {
  109. select.currentNodeKey = select.value
  110. treeRef.value.setCurrentKey(select.value)
  111. const data = treeRef.value.getCurrentNode(select.value)
  112. select.currentNodeLabel = data[props.TreeProps.label]
  113. }
  114. // 监听外部清空数据源 清空组件数据
  115. watch(() => props.modelValue, (v) => {
  116. // 动态赋值
  117. if (v) {
  118. select.value = v
  119. setCurrent()
  120. }else{
  121. clearAll()
  122. }
  123. })
  124. // 回显数据
  125. onMounted(async () => {
  126. await nextTick()
  127. if (select.value) {
  128. setCurrent()
  129. }
  130. })
  131. // 查询在职离职业务员
  132. const handleState = (type) => {
  133. data.state = type
  134. data.treeLoading = true
  135. request({ url: `/admin/dept/treeWithDeptUsers?isLeave=${type}`, method: "GET" }).then(res => {
  136. data.options = res.data.data
  137. data.treeLoading = false
  138. })
  139. }
  140. </script>
  141. <style lang="scss" scoped>
  142. .tree_box {
  143. width: 300px;
  144. }
  145. :deep(.el-scrollbar) {
  146. height: 300px;
  147. .el-select-dropdown__wrap {
  148. max-height: 300px;
  149. overflow: hidden;
  150. .el-select-dropdown__list {
  151. padding: 0;
  152. }
  153. }
  154. }
  155. .el-tree :deep(.is-current>.el-tree-node__content .el-tree-node__label) {
  156. color: var(--el-color-primary);
  157. }
  158. .treeSelectRadio-option-style {
  159. height: 260px !important;
  160. padding: 0 0 10px 0 !important;
  161. margin: 0;
  162. background-color: #fff;
  163. }
  164. .check-box {
  165. padding: 0 16px;
  166. }</style>

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

闽ICP备14008679号