Technologieaustausch

Die Uniapp-Uni-Combox-Datenquelle verwendet das Objekt. Nach der Auswahl können die ID des entsprechenden Elements und der Wert angegeben werden.

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Hintergrund: Die Uni-Combox-Datenquelle in uniApp unterstützt nur das Akzeptieren eindimensionaler Arrays. Es ist nicht möglich, für jede Option eine bestimmte ID anzugeben, und es ist nicht möglich, die ID nach der Auswahl zurückzugeben. Der ursprüngliche Quellcode wird wie folgt geändert:

  1. <template>
  2. <view class="uni-combox" :class="border ? '' : 'uni-combox__no-border'">
  3. <view v-if="label" class="uni-combox__label" :style="labelStyle">
  4. <text>{{label}}</text>
  5. </view>
  6. <view class="uni-combox__input-box">
  7. <input class="uni-combox__input" type="text" :placeholder="placeholder" placeholder-class="uni-combox__input-plac"
  8. v-model="inputVal" @input="onInput" @focus="onFocus" @blur="onBlur" />
  9. <uni-icons :type="showSelector? 'top' : 'bottom'" size="14" color="#999" @click="toggleSelector">
  10. </uni-icons>
  11. </view>
  12. <view class="uni-combox__selector" v-if="showSelector">
  13. <view class="uni-popper__arrow"></view>
  14. <scroll-view scroll-y="true" class="uni-combox__selector-scroll" @scroll="onScroll">
  15. <view class="uni-combox__selector-empty" v-if="filterCandidatesLength === 0">
  16. <text>{{emptyTips}}</text>
  17. </view>
  18. <view class="uni-combox__selector-item" v-for="(item,index) in filterCandidates" :key="index"
  19. @click="onSelectorClick(index)">
  20. <text>{{item[`${labelKey}`]}}</text>
  21. </view>
  22. </scroll-view>
  23. </view>
  24. <uni-icons style="padding-left:20rpx;" class="content-clear-icon" type="clear" color="#c0c4cc" v-if="inputVal"
  25. @click="onClear"></uni-icons>
  26. <!-- :size="clearSize"
  27. :color="msg ? '#dd524d' : focusShow ? primaryColor : '#c0c4cc'" -->
  28. <!-- 新增蒙层,点击蒙层时关闭选项显示 -->
  29. <view class="uni-combox__mask" v-show="showSelector" @click="showSelector = false"></view>
  30. </view>
  31. </template>
  32. <script>
  33. import {
  34. nextTick
  35. } from 'vue'
  36. /**
  37. * Combox 组合输入框
  38. * @description 组合输入框一般用于既可以输入也可以选择的场景
  39. * @tutorial https://ext.dcloud.net.cn/plugin?id=1261
  40. * @property {String} label 左侧文字
  41. * @property {String} labelWidth 左侧内容宽度
  42. * @property {String} placeholder 输入框占位符
  43. * @property {Array} candidates 候选项列表
  44. * @property {String} emptyTips 筛选结果为空时显示的文字
  45. * @property {String} value 组合框的值
  46. */
  47. export default {
  48. name: 'uniCombox',
  49. emits: ['input', 'update:modelValue', 'change'],
  50. props: {
  51. border: {
  52. type: Boolean,
  53. default: true
  54. },
  55. label: {
  56. type: String,
  57. default: ''
  58. },
  59. labelWidth: {
  60. type: String,
  61. default: 'auto'
  62. },
  63. placeholder: {
  64. type: String,
  65. default: ''
  66. },
  67. candidates: {
  68. type: Array,
  69. default () {
  70. return []
  71. }
  72. },
  73. emptyTips: {
  74. type: String,
  75. default: '无匹配项'
  76. },
  77. labelKey: {
  78. type: String,
  79. default: 'dictName'
  80. },
  81. valueKey: {
  82. type: String,
  83. default: 'dictId'
  84. },
  85. // #ifndef VUE3
  86. value: {
  87. type: [String, Number],
  88. default: ''
  89. },
  90. // #endif
  91. // #ifdef VUE3
  92. modelValue: {
  93. type: [String, Number],
  94. default: ''
  95. },
  96. // #endif
  97. },
  98. data() {
  99. return {
  100. showSelector: false,
  101. inputVal: '',
  102. blurTimer: null,
  103. dictVal: "",
  104. filterCandidates: []
  105. }
  106. },
  107. computed: {
  108. labelStyle() {
  109. if (this.labelWidth === 'auto') {
  110. return ""
  111. }
  112. return `width: ${this.labelWidth}`
  113. },
  114. filterCandidatesLength() {
  115. console.log(this.filterCandidates)
  116. return this.filterCandidates.length
  117. }
  118. },
  119. watch: {
  120. // #ifndef VUE3
  121. value: {
  122. handler(newVal) {
  123. this.dictVal = newVal
  124. },
  125. immediate: true
  126. },
  127. // #endif
  128. // 因为获取列表是个异步的过程,需要对列表进行监听
  129. candidates: {
  130. handler(arr) {
  131. if (arr.length > 0 && this.dictVal) {
  132. let obj = arr.find((item, index) => {
  133. return this.dictVal == item[`${this.valueKey}`]
  134. })
  135. this.inputVal = obj[`${this.labelKey}`]
  136. this.$forceUpdate(); // 强制更新 DOM
  137. }
  138. this.filterCandidates = arr.filter((item) => {
  139. return item[`${this.labelKey}`].toString().indexOf(this.inputVal) > -1
  140. })
  141. },
  142. immediate: true,
  143. deep: true
  144. },
  145. // #ifdef VUE3
  146. modelValue: {
  147. handler(newVal) {
  148. // this.inputVal = newVal
  149. this.dictVal = newVal
  150. if (this.candidates.length > 0 && newVal) {
  151. let obj = this.candidates.find((item, index) => {
  152. return newVal == item[`${this.valueKey}`]
  153. })
  154. // 兼容当传入错误的id在待选列表找不到时候的错误
  155. if (obj) {
  156. this.inputVal = obj[`${this.labelKey}`]
  157. } else {
  158. this.inputVal = ''
  159. }
  160. } else if (!newVal) { //当传入的是空值时直接将上一次回填数据清空
  161. this.inputVal = ''
  162. }
  163. },
  164. immediate: true,
  165. deep: true,
  166. },
  167. // #endif
  168. },
  169. methods: {
  170. toggleSelector() {
  171. this.showSelector = !this.showSelector
  172. },
  173. onFocus() {
  174. this.filterCandidates = this.candidates
  175. this.showSelector = true
  176. },
  177. onBlur() {
  178. this.blurTimer = setTimeout(() => {
  179. this.showSelector = false
  180. }, 153)
  181. },
  182. onScroll() { // 滚动时将blur的定时器关掉
  183. if (this.blurTimer) {
  184. clearTimeout(this.blurTimer)
  185. this.blurTimer = null
  186. }
  187. },
  188. onSelectorClick(index) {
  189. // this.inputVal = this.filterCandidates[index]
  190. this.dictVal = this.filterCandidates[index][`${this.valueKey}`]
  191. //this.dictVal 的赋值一定要在this.inputVal前执行,
  192. //因为this.filterCandidates会监听this.inputVal的变化被重新赋值
  193. //这样在选择列表中非第一个选项会报错
  194. this.inputVal = this.filterCandidates[index][`${this.labelKey}`]
  195. this.showSelector = false
  196. this.$emit('input', this.dictVal)
  197. this.$emit('change', this.dictVal)
  198. this.$emit('update:modelValue', this.dictVal)
  199. },
  200. onInput() {
  201. this.filterCandidates = this.candidates.filter((item) => {
  202. console.log(item, this.labelKey)
  203. return item[`${this.labelKey}`].toString().indexOf(this.inputVal) > -1
  204. })
  205. setTimeout(() => {
  206. this.$emit('input', this.dictVal)
  207. this.$emit('update:modelValue', this.dictVal)
  208. })
  209. },
  210. /**
  211. * 清理内容
  212. * @param {Object} event
  213. */
  214. onClear(event) {
  215. this.inputVal = '';
  216. },
  217. }
  218. }
  219. </script>
  220. <style lang="scss">
  221. .uni-combox {
  222. font-size: 14px;
  223. border: 1px solid #DCDFE6;
  224. border-radius: 4px;
  225. // padding: 6px 10px;
  226. padding: 10px 6px 10px 0;
  227. position: relative;
  228. /* #ifndef APP-NVUE */
  229. display: flex;
  230. /* #endif */
  231. // height: 40px;
  232. flex-direction: row;
  233. align-items: center;
  234. // border-bottom: solid 1px #DDDDDD;
  235. }
  236. .uni-combox__label {
  237. font-size: 16px;
  238. line-height: 22px;
  239. padding-right: 10px;
  240. color: #999999;
  241. }
  242. .uni-combox__input-box {
  243. padding-left: 10px;
  244. position: relative;
  245. /* #ifndef APP-NVUE */
  246. display: flex;
  247. /* #endif */
  248. flex: 1;
  249. flex-direction: row;
  250. align-items: center;
  251. }
  252. .uni-combox__input {
  253. flex: 1;
  254. font-size: 14px;
  255. height: 22px;
  256. line-height: 22px;
  257. }
  258. .uni-combox__input-plac {
  259. font-size: 14px;
  260. color: #999;
  261. }
  262. .uni-combox__selector {
  263. /* #ifndef APP-NVUE */
  264. box-sizing: border-box;
  265. /* #endif */
  266. position: absolute;
  267. top: calc(100% + 12px);
  268. left: 0;
  269. width: 100%;
  270. background-color: #FFFFFF;
  271. border: 1px solid #EBEEF5;
  272. border-radius: 6px;
  273. box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  274. z-index: 3;
  275. padding: 4px 0;
  276. }
  277. .uni-combox__selector-scroll {
  278. /* #ifndef APP-NVUE */
  279. max-height: 200px;
  280. box-sizing: border-box;
  281. /* #endif */
  282. }
  283. .uni-combox__selector-empty,
  284. .uni-combox__selector-item {
  285. /* #ifndef APP-NVUE */
  286. display: flex;
  287. cursor: pointer;
  288. /* #endif */
  289. line-height: 36px;
  290. font-size: 14px;
  291. text-align: center;
  292. // border-bottom: solid 1px #DDDDDD;
  293. padding: 0px 10px;
  294. white-space: nowrap;
  295. overflow: auto;
  296. }
  297. .uni-combox__selector-item::-webkit-scrollbar {
  298. width: 0;
  299. height: 0;
  300. }
  301. .uni-combox__selector-item:hover {
  302. background-color: #f9f9f9;
  303. }
  304. .uni-combox__selector-empty:last-child,
  305. .uni-combox__selector-item:last-child {
  306. /* #ifndef APP-NVUE */
  307. border-bottom: none;
  308. /* #endif */
  309. }
  310. // picker 弹出层通用的指示小三角
  311. .uni-popper__arrow,
  312. .uni-popper__arrow::after {
  313. position: absolute;
  314. display: block;
  315. width: 0;
  316. height: 0;
  317. border-color: transparent;
  318. border-style: solid;
  319. border-width: 6px;
  320. }
  321. .uni-popper__arrow {
  322. filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
  323. top: -6px;
  324. left: 10%;
  325. margin-right: 3px;
  326. border-top-width: 0;
  327. border-bottom-color: #EBEEF5;
  328. }
  329. .uni-popper__arrow::after {
  330. content: " ";
  331. top: 1px;
  332. margin-left: -6px;
  333. border-top-width: 0;
  334. border-bottom-color: #fff;
  335. }
  336. .uni-combox__no-border {
  337. border: none;
  338. }
  339. .uni-combox__mask {
  340. width: 100%;
  341. height: 100%;
  342. position: fixed;
  343. top: 0;
  344. left: 0;
  345. z-index: 1;
  346. }
  347. </style>

verwenden:

  1. <uni-combox :candidates="testList" labelKey="text" valueKey="idx" emptyTips='暂无数据' placeholder="请选择"
  2. v-model="groupId" @change="selectGroupab">
  3. </uni-combox>
  4. // 选择区/
  5. const selectGroupab = (val) => {
  6. console.log(' 选择改变回调', val)
  7. }
  8. const groupId =ref('')
  9. const testList =ref([{idx:1,text:'A区'},{idx:2,text:'B区'}])

 

Während es von den Änderungen anderer lernt, ist es auch mit Fehlertoleranz, asynchronem Backfill und Fehlertoleranz für eingehende Nullwerte kompatibel.

Sie können den obigen Code verwenden, um diese Datei direkt in src/uni_modules/uni-combox/components/uni-combox/uni-combox.vue des Projekts zu ersetzen.

Sie können die obige Datei auch direkt als Komponente verwenden, ohne sie zu installieren.