Technology sharing

uniapp uni-combox notitia fonte obiecti utitur.

2024-07-12

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

Background: Fons uni-combox in uniApp solum sustinet acceptionem unius dimensionis vestium. Impossibile est id specificare pro singulis optionibus specificare, et ID post delectu redire impossibile est.

  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>

utere;

  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区'}])

 

Dum discit ab aliis modificationibus, compatitur etiam culpa tolerantiae, backfill asynchrona, et culpa tolerantiae ad nullos inueniendi valores.

Superiore codice uti potes ut hunc fasciculum directe reponere in src/uni_modules/uni-combox/components/uni-combox/uni-combox.vue projecti reponere.

Potes etiam uti fasciculo superiore directo ut componente sine inaugurando.