【面试 - el-select问题及解决】wujie 微前端下子系统 el-select 多选 filterable 过滤失效

目录

  • [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 卡在 truehandleQueryChange 进入后直接 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 的页面
相关推荐
mldong13 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排14 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby606115 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角16 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!16 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰16 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi17 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen18 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马19 小时前
AI源码分析:拆解模型底层实现逻辑
前端
IT_陈寒19 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端