结论:multiSelector 不支持树形嵌套数据,必须拆为三个动态二维数组并监听 columnchange 实时联动;range 必须是二维数组因每列独立渲染,传对象会静默失败;需用 provinces/cities/areas 三段式结构、反向查索引设默认值,并特殊处理直辖市。

直接说结论:别用 mode="multiSelector" 硬套树形数据,它不认嵌套结构;必须拆成三个动态二维数组 + 手动监听 columnchange 事件来维护联动逻辑。
为什么 multiSelector 的 range 必须是二维数组?
因为 picker 组件底层把每一列当成独立滚动器,每列只接受一个纯数组(比如 ["北京", "上海", "广东"]),不能传 [{name:"北京",children:[...]},...] 这类对象嵌套。一旦你把树形数据直接塞进 range,它会静默失败:不报错、不触发 change、滑动卡顿甚至白屏——尤其在安卓低端机上。
常见错误现象:
- 第一列能选,第二列始终显示“请选择城市”且无法滚动
- 选完省之后,市列表没更新,还是初始空数组或上一次残留数据
- H5 平台下 value 改了但视图不刷新,必须手动
this.$nextTick()才生效
columnchange 事件里怎么安全更新下一级 range?
不能等 change 再处理,必须在用户拖动当列时立刻响应,否则会出现“市还没变,区就按旧市加载”的错位。关键点是每次更新都要重置后续列的索引为 0,并强制刷新视图。
- 监听
e.detail.column判断哪一列被拖动 - 若
column === 0(省),则用e.detail.value查出对应省的cityList,赋给multiArray[1],同时设multiIndex = [e.detail.value, 0, 0] - 若
column === 1(市),先确保multiIndex[0]有效,再取cities[multiIndex[0]][e.detail.value].area赋给multiArray[2],并重置第三级索引为0 - 每次修改
multiIndex或multiArray后,必须包一层this.$nextTick(() => this.$forceUpdate())(H5 必加,小程序可酌情)
数据结构怎么组织才不崩?
别用一维扁平数组(查起来慢)、也别用深度嵌套对象(picker 解析不了)。推荐分三块存:
-
provinces:纯数组,每个元素是{name: "广东省", code: "440000"} -
cities:对象,key 是省code,value 是该省所有市数组,如{"440000": [{name:"广州市"}, {name:"深圳市"}]} -
areas:同理,key 是市code,value 是该市所有区数组
这样查的时候就是 cities[provinces[i].code][j] → areas[cities[provinces[i].code][j].code],O(1) 定位,无递归,不卡顿。
默认值怎么设才稳?
value 只能是数字索引数组,比如 [2, 5, 12],不是 ["广东", "深圳", "南山区"]。所以回显前得反向查找:
- 先根据默认省名在
provinces中找索引i - 再用
provinces[i].code查cities得到市数组,找默认市名索引j - 最后用
cities[...][j].code查areas找区索引k - 组合成
[i, j, k]赋给multiIndex
注意:如果后端返回的是完整地区字符串(如“广东省深圳市南山区”),得自己切分+模糊匹配,别指望 picker 自动解析。
最易被忽略的一点:直辖市(北京、上海、天津、重庆)没有“市”这一级,它们的 cities 数组其实是空的,或者要单独映射成“市辖区”。这个逻辑不补全,用户选北京时第二列会空白或崩溃。


















