Vue2 Element Ui表格(Table)组件深层嵌入输入框(Input)组件无法输入异常问题的探究

627 阅读3分钟

这是不久前在项目中发现了这个诡异的用法&问题🙃, 后尝试重新搭建一个环境梳理一遍. 项目已上传到codesandbox.

  • 因笔者能力不足,探究后未能找到一种完美的解决办法,希望后续有大佬能够指点迷津,感激不尽。如读者有类似问题请尝试多种解决办法后综合考虑。

问题的具体表现如图所示或查看codesandbox在线环境. 这是从正常运行的项目中精简后的问题场景。

详见:

GIF_2022-2-24_15-56-47.gif

因分析篇幅较长,为节省时间,可直接尝试下方的解决方式。

分析

  1. 这是笔者第一次见到这种用法很新奇。el-table嵌套着父子两个el-table-column,子级el-table-column使用了自定义插槽,并在头部嵌入el-input。

  2. 当尝试将此用法精简出来梳理时,笔者发现el-table-column的selection、timeFlag和resultArr的组合用法缺一不可。更改其中之一都会使input无法输入

  3. 搜索网上的资料,得到“嵌套层次太深,vue双向绑定失效”这么一个结论。之后以el-input组件为突破点进行源码调试(关于调试方法可以见之前写的一篇文章:juejin.cn/post/706778…

  4. 找到Input源码的setNativeInputValue方法,填入log。

    注意⚠️:笔者这里使用的源码路径是/node_modules/element-ui/lib/input.js

    如果单纯分析源码还是查看input.vue组件源码较为清晰。

    setNativeInputValue: function setNativeInputValue() {
          var input = this.getInput();
          if (!input) return;
          if (input.value === this.nativeInputValue) return;
          console.log('Run setNativeInputValue ', ' 当前value:', this.value, '当前input Value:', input.value);
          input.value = this.nativeInputValue;
        },
    

    WX20220224-2208372x.png

    这里分别输入了 1 2;可以看到运行了两遍setNativeInputValue方法,第一遍props的value值正常,第二遍显示未定义

  5. 为什么会运行两遍?先搜索哪里用到了这个方法。找到两个关键点。

  6. 在782行watch监听nativeInputValue 改变的方法中填入log

    nativeInputValue: function nativeInputValue() {
          console.log('监听nativeInputValue更新', this.value);
          this.setNativeInputValue();
        },
    

    在871行handleInput 方法改造一下并填入log

    handleInput: function handleInput(event) {
          // should not emit input during composition
          // see: https://github.com/ElemeFE/element/issues/10516
          if (this.isComposing) return;
    
          // hack for https://github.com/ElemeFE/element/issues/8548
          // should remove the following line when we don't support IE
          if (event.target.value === this.nativeInputValue) return;
    
          this.$emit('input', event.target.value);
    
          // ensure native input value is controlled
          // see: https://github.com/ElemeFE/element/issues/12850
          this.$nextTick(() => {
            console.log('Run handleInput')
            this.setNativeInputValue()
          });
        },
    

    观察运行结果,如图所示

    WX20220224-2228332x.png

  7. 产生这种结果的影响又是什么?没想通。undefined既然出在handleinput方法那先把this.setNativeInputValue()注释掉再试试。

  8. 结果如图所示

    ezgif-5-308f2e2943.gif

    可以看到三个输入框的输入结果并不一致。和codesandbox所演示的不相同。输入问题虽然已经正常,但是使用这种解决方式并不可取。

  9. 后续因为时间关系无法进行,探究就暂时告一段落。

“解决”办法

1. 使用原生input代替el-input组件

使用原生的input组件代替el-input组件是笔者认为最为保险也是笔者使用的解决办法。

样式上直接仿照el-input写即可。

方法上就需要看迁移成本了

2. 怪异使用

这种怪异的使用方式并不推荐

参照链接:codesandbox.io/s/wen-ti-ce…

3. $forceUpdate

可以尝试在el-input的input方法中调用this.$forceUpdate()

因对笔者应用场景无效,只是作为一个参考。

4. 修改源码

可按照本文的分析思路

参照第7条,注释掉源码中884行this.setNativeInputValue() 方法

可临时解决 但此方式带来的影响未知 极不推荐