2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Contexte : La source de données uni-combox dans uniApp ne prend en charge que les tableaux unidimensionnels. Il est impossible de spécifier un ID spécifique pour chaque option et il est impossible de renvoyer l'ID après la sélection. Le code source d'origine est modifié comme suit :
- <template>
- <view class="uni-combox" :class="border ? '' : 'uni-combox__no-border'">
- <view v-if="label" class="uni-combox__label" :style="labelStyle">
- <text>{{label}}</text>
- </view>
- <view class="uni-combox__input-box">
- <input class="uni-combox__input" type="text" :placeholder="placeholder" placeholder-class="uni-combox__input-plac"
- v-model="inputVal" @input="onInput" @focus="onFocus" @blur="onBlur" />
- <uni-icons :type="showSelector? 'top' : 'bottom'" size="14" color="#999" @click="toggleSelector">
- </uni-icons>
- </view>
- <view class="uni-combox__selector" v-if="showSelector">
- <view class="uni-popper__arrow"></view>
- <scroll-view scroll-y="true" class="uni-combox__selector-scroll" @scroll="onScroll">
- <view class="uni-combox__selector-empty" v-if="filterCandidatesLength === 0">
- <text>{{emptyTips}}</text>
- </view>
- <view class="uni-combox__selector-item" v-for="(item,index) in filterCandidates" :key="index"
- @click="onSelectorClick(index)">
- <text>{{item[`${labelKey}`]}}</text>
- </view>
- </scroll-view>
- </view>
- <uni-icons style="padding-left:20rpx;" class="content-clear-icon" type="clear" color="#c0c4cc" v-if="inputVal"
- @click="onClear"></uni-icons>
- <!-- :size="clearSize"
- :color="msg ? '#dd524d' : focusShow ? primaryColor : '#c0c4cc'" -->
- <!-- 新增蒙层,点击蒙层时关闭选项显示 -->
- <view class="uni-combox__mask" v-show="showSelector" @click="showSelector = false"></view>
- </view>
-
- </template>
-
- <script>
- import {
- nextTick
- } from 'vue'
- /**
- * Combox 组合输入框
- * @description 组合输入框一般用于既可以输入也可以选择的场景
- * @tutorial https://ext.dcloud.net.cn/plugin?id=1261
- * @property {String} label 左侧文字
- * @property {String} labelWidth 左侧内容宽度
- * @property {String} placeholder 输入框占位符
- * @property {Array} candidates 候选项列表
- * @property {String} emptyTips 筛选结果为空时显示的文字
- * @property {String} value 组合框的值
- */
- export default {
- name: 'uniCombox',
- emits: ['input', 'update:modelValue', 'change'],
- props: {
- border: {
- type: Boolean,
- default: true
- },
- label: {
- type: String,
- default: ''
- },
- labelWidth: {
- type: String,
- default: 'auto'
- },
- placeholder: {
- type: String,
- default: ''
- },
- candidates: {
- type: Array,
- default () {
- return []
- }
- },
- emptyTips: {
- type: String,
- default: '无匹配项'
- },
- labelKey: {
- type: String,
- default: 'dictName'
- },
- valueKey: {
- type: String,
- default: 'dictId'
- },
- // #ifndef VUE3
- value: {
- type: [String, Number],
- default: ''
- },
- // #endif
- // #ifdef VUE3
- modelValue: {
- type: [String, Number],
- default: ''
- },
- // #endif
- },
- data() {
- return {
- showSelector: false,
- inputVal: '',
- blurTimer: null,
- dictVal: "",
- filterCandidates: []
- }
- },
- computed: {
- labelStyle() {
- if (this.labelWidth === 'auto') {
- return ""
- }
- return `width: ${this.labelWidth}`
- },
-
- filterCandidatesLength() {
- console.log(this.filterCandidates)
- return this.filterCandidates.length
- }
- },
- watch: {
- // #ifndef VUE3
- value: {
- handler(newVal) {
- this.dictVal = newVal
- },
- immediate: true
- },
- // #endif
-
- // 因为获取列表是个异步的过程,需要对列表进行监听
- candidates: {
- handler(arr) {
- if (arr.length > 0 && this.dictVal) {
- let obj = arr.find((item, index) => {
- return this.dictVal == item[`${this.valueKey}`]
- })
- this.inputVal = obj[`${this.labelKey}`]
- this.$forceUpdate(); // 强制更新 DOM
- }
- this.filterCandidates = arr.filter((item) => {
- return item[`${this.labelKey}`].toString().indexOf(this.inputVal) > -1
- })
- },
- immediate: true,
- deep: true
- },
- // #ifdef VUE3
- modelValue: {
- handler(newVal) {
- // this.inputVal = newVal
- this.dictVal = newVal
- if (this.candidates.length > 0 && newVal) {
- let obj = this.candidates.find((item, index) => {
- return newVal == item[`${this.valueKey}`]
- })
- // 兼容当传入错误的id在待选列表找不到时候的错误
- if (obj) {
- this.inputVal = obj[`${this.labelKey}`]
- } else {
- this.inputVal = ''
- }
- } else if (!newVal) { //当传入的是空值时直接将上一次回填数据清空
- this.inputVal = ''
- }
- },
- immediate: true,
- deep: true,
- },
- // #endif
- },
- methods: {
- toggleSelector() {
- this.showSelector = !this.showSelector
- },
- onFocus() {
- this.filterCandidates = this.candidates
- this.showSelector = true
- },
- onBlur() {
- this.blurTimer = setTimeout(() => {
- this.showSelector = false
- }, 153)
- },
- onScroll() { // 滚动时将blur的定时器关掉
- if (this.blurTimer) {
- clearTimeout(this.blurTimer)
- this.blurTimer = null
- }
- },
- onSelectorClick(index) {
- // this.inputVal = this.filterCandidates[index]
- this.dictVal = this.filterCandidates[index][`${this.valueKey}`]
- //this.dictVal 的赋值一定要在this.inputVal前执行,
- //因为this.filterCandidates会监听this.inputVal的变化被重新赋值
- //这样在选择列表中非第一个选项会报错
- this.inputVal = this.filterCandidates[index][`${this.labelKey}`]
- this.showSelector = false
- this.$emit('input', this.dictVal)
- this.$emit('change', this.dictVal)
- this.$emit('update:modelValue', this.dictVal)
- },
- onInput() {
- this.filterCandidates = this.candidates.filter((item) => {
- console.log(item, this.labelKey)
- return item[`${this.labelKey}`].toString().indexOf(this.inputVal) > -1
- })
- setTimeout(() => {
- this.$emit('input', this.dictVal)
- this.$emit('update:modelValue', this.dictVal)
- })
- },
- /**
- * 清理内容
- * @param {Object} event
- */
- onClear(event) {
- this.inputVal = '';
- },
- }
- }
- </script>
-
- <style lang="scss">
- .uni-combox {
- font-size: 14px;
- border: 1px solid #DCDFE6;
- border-radius: 4px;
- // padding: 6px 10px;
- padding: 10px 6px 10px 0;
- position: relative;
- /* #ifndef APP-NVUE */
- display: flex;
- /* #endif */
- // height: 40px;
- flex-direction: row;
- align-items: center;
- // border-bottom: solid 1px #DDDDDD;
- }
-
- .uni-combox__label {
- font-size: 16px;
- line-height: 22px;
- padding-right: 10px;
- color: #999999;
- }
-
- .uni-combox__input-box {
- padding-left: 10px;
- position: relative;
- /* #ifndef APP-NVUE */
- display: flex;
- /* #endif */
- flex: 1;
- flex-direction: row;
- align-items: center;
- }
-
- .uni-combox__input {
- flex: 1;
- font-size: 14px;
- height: 22px;
- line-height: 22px;
- }
-
- .uni-combox__input-plac {
- font-size: 14px;
- color: #999;
- }
-
- .uni-combox__selector {
- /* #ifndef APP-NVUE */
- box-sizing: border-box;
- /* #endif */
- position: absolute;
- top: calc(100% + 12px);
- left: 0;
- width: 100%;
- background-color: #FFFFFF;
- border: 1px solid #EBEEF5;
- border-radius: 6px;
- box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
- z-index: 3;
- padding: 4px 0;
- }
-
- .uni-combox__selector-scroll {
- /* #ifndef APP-NVUE */
- max-height: 200px;
- box-sizing: border-box;
- /* #endif */
- }
-
- .uni-combox__selector-empty,
- .uni-combox__selector-item {
- /* #ifndef APP-NVUE */
- display: flex;
- cursor: pointer;
- /* #endif */
- line-height: 36px;
- font-size: 14px;
- text-align: center;
- // border-bottom: solid 1px #DDDDDD;
- padding: 0px 10px;
- white-space: nowrap;
- overflow: auto;
- }
-
- .uni-combox__selector-item::-webkit-scrollbar {
- width: 0;
- height: 0;
- }
-
- .uni-combox__selector-item:hover {
- background-color: #f9f9f9;
- }
-
- .uni-combox__selector-empty:last-child,
- .uni-combox__selector-item:last-child {
- /* #ifndef APP-NVUE */
- border-bottom: none;
- /* #endif */
- }
-
- // picker 弹出层通用的指示小三角
- .uni-popper__arrow,
- .uni-popper__arrow::after {
- position: absolute;
- display: block;
- width: 0;
- height: 0;
- border-color: transparent;
- border-style: solid;
- border-width: 6px;
- }
-
- .uni-popper__arrow {
- filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
- top: -6px;
- left: 10%;
- margin-right: 3px;
- border-top-width: 0;
- border-bottom-color: #EBEEF5;
- }
-
- .uni-popper__arrow::after {
- content: " ";
- top: 1px;
- margin-left: -6px;
- border-top-width: 0;
- border-bottom-color: #fff;
- }
-
- .uni-combox__no-border {
- border: none;
- }
-
- .uni-combox__mask {
- width: 100%;
- height: 100%;
- position: fixed;
- top: 0;
- left: 0;
- z-index: 1;
- }
- </style>
utiliser:
- <uni-combox :candidates="testList" labelKey="text" valueKey="idx" emptyTips='暂无数据' placeholder="请选择"
- v-model="groupId" @change="selectGroupab">
- </uni-combox>
- // 选择区/苑
- const selectGroupab = (val) => {
- console.log(' 选择改变回调', val)
-
- }
- const groupId =ref('')
- const testList =ref([{idx:1,text:'A区'},{idx:2,text:'B区'}])
Tout en apprenant des modifications apportées par d'autres personnes, il est également compatible avec la tolérance aux pannes, le remplissage asynchrone et la tolérance aux pannes pour les valeurs nulles entrantes.
Vous pouvez utiliser le code ci-dessus pour remplacer directement ce fichier dans le fichier src/uni_modules/uni-combox/components/uni-combox/uni-combox.vue du projet.
Vous pouvez également utiliser le fichier ci-dessus directement comme composant sans l'installer.