目录
- [1. 问题描述](#1. 问题描述)
- [2. wujie 微前端下 el-select 多选 filterable 过滤失效问题修复](#2. wujie 微前端下 el-select 多选 filterable 过滤失效问题修复)
-
- [2.1 问题现象](#2.1 问题现象)
- [2.2 根因分析](#2.2 根因分析)
-
- [2.2.1 问题一:事件对象在防抖延迟期间失效](#2.2.1 问题一:事件对象在防抖延迟期间失效)
- [2.2.2 问题二:isOnComposition 状态被错误锁定](#2.2.2 问题二:isOnComposition 状态被错误锁定)
- [2.3 解决方案](#2.3 解决方案)
- [2.4 修复原理](#2.4 修复原理)
- [2.5 适用范围](#2.5 适用范围)
- [2.6 相关文件](#2.6 相关文件)
1. 问题描述
- 系统A 单独运行的时候
select下拉数据不论多选还是单选,filter过滤都正常,- 但是系统A通过
wujie的方式嵌到系统B时,
- 系统A单选的
select使用filter过滤时正常,- 多选的
select使用filter过滤时下拉数据没有变(没有触发过滤),- 这是为什么?怎么解决
2. wujie 微前端下 el-select 多选 filterable 过滤失效问题修复
2.1 问题现象
| 环境 | 单选 + filterable | 多选 + filterable |
|---|---|---|
| 独立运行 | 正常 | 正常 |
| wujie 嵌入 | 正常 | 失效(输入字母无过滤,输入中文报错) |
错误信息:Uncaught TypeError: Cannot read properties of null (reading 'value')
2.2 根因分析
Element UI 的 el-select 在单选 和多选 模式下使用了不同的过滤输入处理路径:
- 单选模式 :
debouncedOnInputChange→ 内部读取this.query(组件响应式数据),不依赖事件对象 - 多选模式 :
debouncedQueryChange→ 内部读取e.target.value(事件对象属性)
debouncedQueryChange 是一个 300ms 防抖函数,在 wujie 沙箱环境中存在两个问题:
2.2.1 问题一:事件对象在防抖延迟期间失效
wujie 会代理/合成事件(isTrusted: false),这些合成事件在 handler 返回后会被回收。300ms 后防抖回调执行时 e.target 已为 null,导致:
- 输入字母 → 取不到值,过滤不触发
- 输入中文 → 报错
Cannot read properties of null (reading 'value')
2.2.2 问题二:isOnComposition 状态被错误锁定
wujie 沙箱中多选输入框动态创建时,可能触发 compositionstart 但不触发 compositionend,导致 Element UI 内部 isOnComposition 卡在 true,handleQueryChange 进入后直接 return,过滤逻辑被跳过。
2.3 解决方案
在 src/main.js 的 wujie 补丁块(if (window.$wujie) { ... })中添加以下代码,完全替换 debouncedQueryChange,不依赖 event 对象,改为直接从 DOM 读值:
js
if (window.$wujie) {
const components = ['ElSelect', 'ElDatePicker', 'ElTimePicker', 'ElCascader', 'ElAutocomplete']
components.forEach((name) => {
const comp = Vue.component(name)
if (!comp) return
Vue.component(name, {
extends: comp,
props: {
popperAppendToBody: { type: Boolean, default: false },
appendToBody: { type: Boolean, default: false },
popperClass: { type: [String, Array], default: 'insert-wujie_popper-class' },
collapseTags: { type: Boolean, default: true }
}
})
})
// 修复 wujie 环境下多选 el-select filterable 过滤无效问题
// 根因:debouncedQueryChange 是防抖函数(延迟300ms执行),内部通过 e.target.value 取值,
// 但 wujie 沙箱中事件对象在防抖延迟期间会被回收/失效(isTrusted:false 的合成事件尤其严重),
// 导致延迟回调执行时 e.target 已为 null 或值丢失,过滤逻辑不触发或报错
// 解决:完全不依赖 event 对象,防抖回调内直接从 DOM 读取输入值
Vue.mixin({
beforeMount() {
if (this.$options.name === 'ElSelect' && this.debouncedQueryChange) {
const vm = this
this.debouncedQueryChange = debounce(function() {
// 重置 isOnComposition,防止 wujie 下 compositionend 未触发导致阻塞
vm.isOnComposition = false
// 直接从 DOM 读取多选过滤输入框的当前值,不依赖可能已失效的 event 对象
const input = vm.$el && vm.$el.querySelector('.el-select__input')
const val = input ? input.value : vm.query || ''
vm.handleQueryChange(val)
}, 300)
}
}
})
}
注意:
debounce来自项目已引入的lodash.debounce
2.4 修复原理
用户输入 → input 事件触发 debouncedQueryChange()
↓
[等待 300ms 防抖]
↓
┌─── 原始方案(失效)────┐ ┌─── 新方案(可靠)─────┐
│ 读 e.target.value │ │ 读 DOM input.value │
│ (事件已被 wujie 回收) │ │ (DOM 元素始终存在) │
│ → null → 报错/无值 │ │ → 取到正确输入值 │
└────────────────────────┘ └────────────────────────┘
↓
vm.isOnComposition = false
↓
vm.handleQueryChange(val) → 过滤生效 ✓
2.5 适用范围
所有使用 Element UI 2.x + wujie 微前端 的项目,只要出现多选 select 过滤失效的问题,都可以使用此方案修复。
2.6 相关文件
- 修复位置:
src/main.js(wujie 补丁块内) - 影响组件:所有使用
el-select+multiple+filterable的页面

