返回博客

下拉选项 value 对不上主数据 key,Element UI 静默失败显示原始编码

给后台管理系统的列表页加筛选下拉时,最顺手的操作是:找一个现成的"配置型 API"复用。这条路看起来省事,但有一个静默失败的陷阱——组件不抛错、UI 看起来"工作了",但 tag 显示的是 CT0003 而不是 金珍珠会员

现象

在某后台的会员等级筛选下拉上,用户选择后,筛选 tag 和 select 输入框里显示的不是"金珍珠会员"之类的可读名称,而是 CT0003 这样的内部编码。切换选项、刷新数据均无改善,控制台零报错。

根因

系统里确实存在一个 /api/levelOptions 配置接口,返回结构大致是:

[
  { "value": "金珍珠会员", "label": "金珍珠会员" },
  { "value": "白银会员",   "label": "白银会员"   }
]

注意:value 字段存的是中文名

而主数据列表每行的等级字段是:

{ "level_code": "CT0003", "level_name": "金珍珠会员" }

v-model 绑定的是 row.level_code,值为 "CT0003"

Element UI 的 el-select 在渲染时用 v-model 的值去遍历所有 <el-option>:value,找不到完全相同的字符串 → 回退逻辑:直接把 v-model 的原始值显示在输入框里。

整个过程零警告、零报错,UI 看起来"响应了",只是显示的是原始 code 而非 label。

坑:配置 API 的 value 字段可能是中文名,不是 code

复用配置型 API 前必须验证三方字符串完全相等:

  1. v-model 的初始值类型/格式
  2. 配置 API 返回的 :value 字段实际内容
  3. 主数据 row 里 filter 用的字段实际内容

任一不一致,Element UI / vant / antd 的 select 系组件都会静默失败——不报错,但 tag 显示的是原始 v-model 值,而不是 label。

# 快速验证三方
curl '/api/levelOptions' | jq '.data[0]'       # value 是 code 还是中文名?
grep -n 'level_code\|level_name' src/views/...  # 主数据带哪些字段?
grep -n 'v-model' src/views/.../filter.vue      # v-model 初值是什么?

正解

方案一(推荐):从主数据派生下拉选项

主数据每行既有 code 又有 name 时,直接从 tableData 派生,跳过配置 API:

computed: {
  levelOptions() {
    const seen = new Map()
    for (const row of (this.tableData || [])) {
      for (const lv of (row.by_level || [])) {
        if (lv.level_code && !seen.has(lv.level_code)) {
          seen.set(lv.level_code, {
            value: lv.level_code,   // 与 v-model / filter 字段恒等
            label: lv.level_name || lv.level_code,
          })
        }
      }
    }
    return Array.from(seen.values())
  }
}

三个额外收益:

  • value 与主数据 join key 字符串恒等,永远不会错位
  • 自动只展示当前数据集真实出现过的选项,噪音少
  • 少一次 HTTP 请求

方案二:保留配置 API + 后端补对齐字段

如果配置 API 被多个页面共用、不方便改,则让后端 SQL 在主数据里额外 SELECT 一个与配置 API value 格式一致的字段,用那个字段做 v-model,而不是现有的 code 字段。

正解:value 必须与 v-model 字符串完全相等

方案一适用条件:主数据每行同时携带 code(用于 filter)和 name(用于展示)。

方案二适用条件:配置 API 已有全量选项(含当前无数据的枚举项),或多列表共用同一份选项。

两种方案的核心原则一样:前端 select 的 :value = v-model 绑定值 = 主数据 filter 字段,三方字符串完全相等。

一句话外卖

复用"配置型 API"做下拉选项之前,先 curl 一下它返回的 value 字段,确认它和主数据 join key 字符串完全相同——否则宁可从主数据派生,静默失败比崩溃更难排查。