本地可多选线上仅单选:Checkbox组绑定数组在线环境异常
多选列筛选在生产环境仅能单选的排查与解决
问题现象
- 本地开发环境(localhost):基于Checkbox组的列筛选功能正常,可勾选多个选项显示对应列,操作状态通过LocalStorage持久化。
- 线上生产环境:每次仅能勾选一个Checkbox,勾选第二个时第一个自动取消,疑似绑定的
selectedFieldKeys变量未被识别为数组。
效果对比
本地效果:
线上效果:
相关代码
Template部分
<template> <b-row class="d-none d-sm-block" v-if="selectedPropertyId && tableLayout"> <b-col class="mb-3"> <b-form-checkbox-group inline v-model="selectedFieldKeys" :options="selectableFields" text-field="label" value-field="key" /> </b-col> </b-row> <b-row class="d-sm-none" v-if="selectedPropertyId && tableLayout"> <b-col class="mb-3"> <b-form-checkbox-group stacked v-model="selectedFieldKeys" :options="selectableFields" text-field="label" value-field="key" /> </b-col> </b-row> <b-table v-if="selectedPropertyId && tableLayout" :items="units" :fields="fields" :filter="filterList" striped :empty-text="$t('emptyText')" :empty-filtered-text="$t('emptyFilteredText')" search-placeholder="searchInList" :per-page="[500, 1000]" sort-by="unitName" primary-key="dummyId" small="small" foot-clone clear-foot-clone no-footer-sorting sticky-header="67vh" include-filter /> </template>
Script部分
<script> import moment from 'moment'; import LoadingMessage from '@/components/LoadingMessage'; import {listService} from '@/services/lists'; import {propertyService} from '@/services/property'; const localStorageKeyName = 'visibleFieldNames'; export default { data() { return { selectedFieldKeys: [], selectedPropertyId: null, loadingList: false, properties: [], units: null, allUnits: null }; }, props: { initialPropertyId: { type: String, default: null } }, methods: { load() { propertyService.list() .then(result => this.properties = result.data) .catch(error => console.error(error)); }, getList() { if (this.selectedPropertyId) { this.units = null; this.allUnits = null; this.loadingList = true; const propertyId = this.selectedPropertyId === 'all' ? null : this.selectedPropertyId; listService.rentalListReport(propertyId) .then(result => { this.units = result.data; this.allUnits = this.units; this.loadingList = false; }) .catch(error => { console.error(error); this.loadingList = false; }); } }, normalColumn(key, label) { return { key, label: this.$t(label ?? key), sortable: true }; }, enumColumn(key, prefix, label) { return Object.assign(this.normalColumn(key, label), { formatter: value => value && this.$t(`${prefix}.${value}`), sortByFormatted: true }); }, numberColumn(key, label) { return Object.assign(this.normalColumn(key, label), { template: { type: 'number', format: { minimumFractionDigits: '2', maximumFractionDigits: '2' }, foot: sum } }); }, dateColumn(key, label) { return Object.assign(this.normalColumn(key, label), { template: {type: 'date', format: 'L'} }); } }, computed: { selectableFields() { return [ { key: 'unitName', label: this.$t('unit'), sortable: true, template: { type: 'link', label: data => data.item.unitName, to: data => `/units/${data.item.unitId}`, foot: count } }, this.normalColumn('stageName', 'stage'), this.normalColumn('unitNumber'), this.enumColumn('status', 'model.unit.status'), this.normalColumn('numberWaitingList', 'waitingList'), this.normalColumn('reserved'), this.enumColumn('unitType', 'model.unit.types', 'type'), this.normalColumn('internalType'), this.dateColumn('availableDate'), this.dateColumn('rentEndDate'), this.numberColumn('privateArea', 'model.unit.fields.PRIVATE_AREA'), this.numberColumn('commercialArea', 'model.unit.fields.COMMERCIAL_AREA'), this.numberColumn('numberRooms', 'model.unit.fields.NUMBER_ROOMS'), this.enumColumn('rentalPeriod', 'model.rentalPeriod'), this.numberColumn('rentOnAvailableDate', 'rentWithoutVat'), this.numberColumn('rentVatOnAvailableDate', 'rentVat'), this.numberColumn('rentPerYearPerM2OnAvailableDate', 'rentPerYearPerM2WithoutVat'), this.numberColumn('rentPerYearPerM2VatOnAvailableDate', 'rentPerYearPerM2WithVat'), this.numberColumn('depositOnAvailableDate', 'depositWithoutVat'), this.numberColumn('depositVatOnAvailableDate', 'depositWithVat'), this.numberColumn('prepaymentOnAvailableDate', 'prepaymentWithoutVat'), this.numberColumn('prepaymentVatOnAvailableDate', 'prepaymentWithVat'), this.numberColumn('acontoOnAvailableDate', 'acontoWithoutVat'), this.numberColumn('acontoVatOnAvailableDate','acontoWithVat'), ]; }, fields() { return this.selectableFields.filter(field => this.selectedFieldKeys?.includes(field.key)).concat( { key: 'unitUnavailable', label: '', sortable: true, template: { type: 'status' } }, { key: 'actions', template: { type: 'actions', head: [ { type: 'export' } ], cell: this.actions } } ) } }, created() { this.selectedPropertyId = this.initialPropertyId; try { this.selectedFieldKeys = JSON.parse(window.localStorage.getItem(localStorageKeyName)); } catch { this.selectedFieldKeys = this.selectableFields.map(field => field.key); } }, watch: { selectedPropertyId: 'getList', selectedFieldKeys: { deep: true, handler() { window.localStorage.setItem(localStorageKeyName, JSON.stringify(this.selectedFieldKeys)); } } } }; </script>
排查与解决
1. 修复LocalStorage初始化的类型校验
线上环境可能存在旧的非数组格式的LocalStorage数据(比如之前误存的单个字符串),导致selectedFieldKeys被赋值为非数组,Bootstrap-Vue的Checkbox组会自动切换为单选模式。修改created钩子中的初始化逻辑,强制校验数组类型:
created() { this.selectedPropertyId = this.initialPropertyId; try { const savedData = JSON.parse(window.localStorage.getItem(localStorageKeyName)); // 确保赋值的是数组,否则用默认全选 this.selectedFieldKeys = Array.isArray(savedData) ? savedData : this.selectableFields.map(field => field.key); } catch { this.selectedFieldKeys = this.selectableFields.map(field => field.key); } }
2. 显式设置Checkbox组的multiple属性
虽然Bootstrap-Vue的b-form-checkbox-group默认是多选模式,但线上打包优化可能丢失默认配置,显式添加multiple属性确保多选行为:
<b-form-checkbox-group inline v-model="selectedFieldKeys" :options="selectableFields" text-field="label" value-field="key" multiple />
3. 确保响应式更新正常
避免直接替换数组引用,改用Vue的数组方法或splice来更新,确保响应式触发:
// 初始化时用splice替代直接赋值 const defaultKeys = this.selectableFields.map(field => field.key); this.selectedFieldKeys.splice(0, this.selectedFieldKeys.length, ...(Array.isArray(savedData) ? savedData : defaultKeys));
4. 检查打包压缩配置
如果使用Webpack/Vite等打包工具,检查是否有过度压缩导致数组逻辑异常。可以在selectedFieldKeys定义处添加注释禁止压缩:
data() { return { /* webpackMode: "eager" */ selectedFieldKeys: [], // ...其他数据 }; }
内容的提问来源于stack exchange,提问作者Scandidi
相关产品推荐
相关产品推荐

