index.vue 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. <template>
  2. <div>
  3. <van-field v-model="text" v-bind="$attrs" readonly is-link :name="name" :label="label" @click="show = !show" :rules="rules" :required="required" />
  4. <van-popup :show="show" round position="bottom">
  5. <van-search v-if="search" v-model="keyWord" placeholder="请输入搜索关键词" />
  6. <van-picker v-model="selectedValues" :columns="filterColumns" :column-field-names="customFieldName" show-toolbar :title="label" @cancel="show = false, keyWord = null" @confirm="onConfirm">
  7. <template #empty>
  8. <van-empty :image="emptyImage" image-size="80" description="暂无数据" />
  9. </template>
  10. </van-picker>
  11. </van-popup>
  12. </div>
  13. </template>
  14. <script>
  15. import emptyImage from '@/assets/images/custom-empty-image.png';
  16. import { ref, watch, nextTick } from 'vue';
  17. import { Field, Popup, Picker } from 'vant';
  18. export default {
  19. components: {
  20. 'van-field': Field,
  21. 'van-popup': Popup,
  22. 'van-picker': Picker,
  23. },
  24. props: {
  25. // 传入组件的下拉选项原始数组
  26. columns: {
  27. type: Array,
  28. required: true,
  29. },
  30. // 表单项
  31. label: String,
  32. // 父组件绑定值
  33. modelValue: String,
  34. // 自定义 columns 结构中的字段, 结构不一样就调用组件时传入新的格式, 不然组件无法解析
  35. customFieldName: {
  36. type: Object,
  37. // 默认选项格式
  38. default: () => ({
  39. text: 'text',
  40. value: 'value',
  41. }),
  42. },
  43. // 组件name
  44. name: String,
  45. // 校验规则
  46. rules: Array,
  47. // 是否显示*标
  48. required: Boolean,
  49. // 是否开启搜索功能
  50. search: {
  51. type: Boolean,
  52. default: false,
  53. },
  54. },
  55. data() {
  56. return {
  57. // 空状态图片
  58. emptyImage,
  59. // 用于操作的下拉选项数组(如筛选等)
  60. filterColumns: [],
  61. // 选择的选项
  62. selectedValues: [],
  63. // 组件可见状态
  64. show: false,
  65. // 显示文本
  66. text: '',
  67. // 选择的值
  68. code: '',
  69. // 搜索关键词
  70. keyWord: null,
  71. };
  72. },
  73. watch: {
  74. modelValue(newVal) {
  75. this.reShow();
  76. },
  77. columns(newVal) {
  78. this.filterColumns = newVal;
  79. this.reShow();
  80. },
  81. code(newVal) {
  82. // 更新绑定值
  83. this.$emit('update:modelValue', newVal);
  84. // 传回change事件
  85. this.$emit('change', this.code);
  86. },
  87. // 监听搜索关键字的变化
  88. keyWord(newVal) {
  89. const results = [];
  90. this.columns.forEach((item) => {
  91. if (item.text.indexOf(newVal) > -1) {
  92. results.push(item);
  93. }
  94. });
  95. this.filterColumns = results;
  96. },
  97. },
  98. mounted() {
  99. this.filterColumns = this.columns;
  100. nextTick(() => {
  101. this.reShow();
  102. });
  103. },
  104. methods: {
  105. // 确认选择后触发的方法
  106. onConfirm({ selectedOptions }) {
  107. // 重置关键字
  108. this.keyWord = null;
  109. this.text = selectedOptions[0][this.customFieldName.text];
  110. this.code = selectedOptions[0][this.customFieldName.value];
  111. this.show = false;
  112. },
  113. // 回显方法
  114. reShow() {
  115. // 判断传入的modelValue是否为空
  116. if (this.modelValue) {
  117. // 不为空正常给值
  118. this.filterColumns.forEach((column) => {
  119. if (column[this.customFieldName.value] === this.modelValue) {
  120. this.text = column[this.customFieldName.text];
  121. // 主要是解决父级修改v-model绑定的值之后,组件中没联动变化
  122. this.selectedValues[0] = column[this.customFieldName.value];
  123. }
  124. });
  125. } else {
  126. // 为空需要清空组件中之前选择的数据
  127. this.text = '';
  128. this.code = '';
  129. this.selectedValues = [];
  130. }
  131. },
  132. },
  133. };
  134. </script>