cwg-combox.vue 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. <template>
  2. <view class="cwg-combox">
  3. <template v-if="disabled">
  4. <view class="disabled-text">{{ innerText }}</view>
  5. </template>
  6. <template v-if="!disabled">
  7. <!-- 可搜索模式 -->
  8. <uni-combox v-if="filterable" v-model="innerText" :candidates="textList" :clearable="clearable"
  9. :placeholder="placeholder" :disabled="disabled" @input="handleComboxChange" />
  10. <!-- 普通下拉模式 -->
  11. <uni-data-select v-else v-model="innerValue" :localdata="options" :clear="clearable"
  12. :placeholder="placeholder" :multiple="multiple" :disabled="disabled" @change="handleSelectChange" />
  13. </template>
  14. </view>
  15. </template>
  16. <script setup>
  17. import { ref, computed, watch, onMounted } from 'vue'
  18. const props = defineProps({
  19. value: [String, Number],
  20. options: {
  21. type: Array,
  22. default: () => []
  23. },
  24. filterable: {
  25. type: Boolean,
  26. default: false
  27. },
  28. placeholder: String,
  29. clearable: {
  30. type: Boolean,
  31. default: true
  32. },
  33. multiple: {
  34. type: Boolean,
  35. default: false
  36. },
  37. disabled: Boolean
  38. })
  39. const emit = defineEmits(['update:value', 'change'])
  40. /**
  41. * 内部状态
  42. */
  43. const innerValue = ref(props.value)
  44. const innerText = ref('')
  45. /**
  46. * 提取 text 列表(给 combox 用)
  47. */
  48. const textList = computed(() =>
  49. props.options.map(item => item.text)
  50. )
  51. /**
  52. * value → text 映射
  53. */
  54. const updateTextByValue = (val) => {
  55. if (!val) {
  56. innerText.value = ''
  57. return
  58. }
  59. const item = props.options.find(i => i.value === val)
  60. innerText.value = item ? item.text : ''
  61. }
  62. /**
  63. * 组件挂载时初始化
  64. */
  65. onMounted(() => {
  66. if (props.value) {
  67. innerValue.value = props.value
  68. updateTextByValue(props.value)
  69. }
  70. })
  71. /**
  72. * value 改变时同步内部状态
  73. */
  74. watch(
  75. () => props.value,
  76. (val) => {
  77. innerValue.value = val
  78. updateTextByValue(val)
  79. }
  80. )
  81. /**
  82. * options 改变时重新计算显示文本(回显)
  83. */
  84. watch(
  85. () => props.options,
  86. () => {
  87. if (props.value) {
  88. updateTextByValue(props.value)
  89. }
  90. },
  91. { deep: true }
  92. )
  93. /**
  94. * 普通 select 改变
  95. */
  96. const handleSelectChange = (val) => {
  97. innerValue.value = val
  98. updateTextByValue(val)
  99. emit('update:value', val)
  100. emit('change', val)
  101. }
  102. /**
  103. * combox 改变
  104. */
  105. const handleComboxChange = (text) => {
  106. const item = props.options.find(i => i.text === text)
  107. if (item) {
  108. innerValue.value = item.value
  109. emit('update:value', item.value)
  110. emit('change', item.value)
  111. }
  112. }
  113. </script>
  114. <style lang="scss" scoped>
  115. .disabled-text {
  116. height: px2rpx(35);
  117. padding: 0 px2rpx(12);
  118. border-radius: px2rpx(4);
  119. line-height: px2rpx(35);
  120. font-size: px2rpx(15);
  121. background: #f5f5f5;
  122. color: #d5d5d5;
  123. }
  124. </style>