级联选择+模糊搜索必须分层处理,仅在当前激活层级过滤可展开子节点或可选叶子节点,避免破坏层级关系;uni-app中推荐用u-picker配合防抖加载、手动控制columns渲染,并严格同步currentlevel与清空状态。

级联选择 + 模糊搜索必须分层处理
不能把所有数据一次性塞进一个 filter 里暴力匹配,否则会破坏层级关系(比如搜“北京朝阳”,却把“上海朝阳区”也混进来)。真实场景中,用户输入时应只在当前展开的层级做匹配,且仅展示该层级下**可展开的子节点**或**可选的叶子节点**。
常见错误是:用 inputValue 对整个树形数据 data 做 .filter(item => item.label.includes(inputValue)) —— 这会导致路径断裂、无法回溯父级、点击后跳转错层。
- 正确做法:维护当前激活的层级索引(如
currentLevel = 0),只对levelData[currentLevel]做模糊过滤 - 若某节点有
children字段,且过滤后仍有子项,则显示为可展开项;若无children但匹配成功,则作为可选项高亮 - 每次输入后重置后续层级(
levelData.splice(currentLevel + 1)),避免残留旧数据
uni-app 中推荐用 u-picker + 自定义搜索栏组合
原生 uni-data-picker 不支持输入过滤,u-picker(uView 3.x)提供 show-toolbar 和 custom-item 插槽,能嵌入搜索框并控制列表渲染逻辑。
关键点不是“换组件”,而是接管 columns 的生成时机:
- 监听搜索输入,调用防抖函数(如
debounce(() => this.loadColumns(), 300)) -
loadColumns()内部根据当前层级和关键词请求或过滤对应数据,返回扁平化数组(非树结构) - 将结果赋给
columns[activeColumnIndex],触发u-picker重新渲染该列 - 禁用默认搜索(
searchable: false),完全由你控制过滤行为
示例片段:
columns: [ [], [], [] ], // 三列,每列独立数据<br>activeColumnIndex: 0,<br>inputValue: '',<br>methods: {<br> onInput(val) {<br> this.inputValue = val;<br> this.debouncedLoad();<br> },<br> loadColumns() {<br> // 只查第 activeColumnIndex 层,且 label 包含 inputValue<br> this.columns[this.activeColumnIndex] = this.allData[this.activeColumnIndex].filter(item =><br> item.label.includes(this.inputValue)<br> );<br> }<br>}
滚动时下拉面板自动收起?这是 touchend 监听范围问题
很多开发者照搬 aui-autocomplete 的 @touchend="handleTouched",结果发现滑动页面时面板闪退——因为 touchend 在 scroll-view 或 page 容器上触发太频繁,且无法区分是点击还是滑动结束。
真正可靠的方式是监听 scroll-view 的 @scroll 事件,并判断是否发生位移:
- 记录初始
scrollTop,在@scroll中对比变化量,若 delta > 2px 则认为是滑动,调用this.$refs.picker.close() - 不要依赖
touchend,它在 iOS 上可能延迟触发,且 H5 和小程序行为不一致 - 如果使用
u-picker,直接设置closeOnClickOverlay为true,再配合自定义 overlay 点击关闭即可
多端兼容要注意字段映射和空状态处理
小程序真机调试时,常出现“搜索无结果但面板不更新”——根本原因是 setData 异步性 + 条件渲染判断松散。例如:v-if="columns[1].length" 在 H5 可能为 true,但在微信小程序里因数据未及时同步仍为 false。
务必做到:
- 每次更新
columns后,显式设置loading: false和empty: columns[current].length === 0 - 字段名统一用
label/value,避免在不同平台解析出错(如支付宝小程序对text字段敏感) - 远程搜索时,H5 可走 CORS 接口,小程序必须配置
request合法域名,且接口需返回标准树形或扁平结构,不要混用
最易被忽略的是:搜索态下的“清空”按钮点击后,没重置 currentLevel 和所有 columns,导致后续选择从错误层级开始。这个状态必须和搜索输入双向绑定,而不是仅靠 UI 清空 input。










