写这篇博客的时候已经快11点了,但是这么奇葩的bug我遇到了并且解决了,还是很开心的

bug复现场景:

el-table里使用了treeselect,因为行数太多,列表里大量使用了treeselect非常卡顿,el-table的性能没有vxe-table好,所以换成了vxe-table的可编辑列表。

vxe-table的可编辑列表性能是真的好,其实如果不是奇怪的需求,单说vxe-table本身,还是很好用的,文档也很齐全。

vxe-table的可编辑列表有两个插槽,一个是默认插槽,一个是编辑插槽。如果没有特殊要求,单用编辑插槽其实啥问题都没有。

但是要求是列表不能有抖动的感觉,看文档,点击哪一行会变成下拉框,没有点击的什么样式都没有,要求要统一。

element ui Switch 开关如何在table中使用 element ui select 插槽_插槽


但是如果默认插槽和编辑插槽都用树插件的话,还是会遇到卡顿的现象。

所以默认插槽只能是div

在默认插槽为div的情况下,要求一点击输入框就获取焦点并打开树下拉框
难点就在于它是从div切换成树插件

反正是要解决,那就上代码吧

我实现的方式写自定义指令

定义一个js文件,myFocus.js

import Vue from 'vue'
//自定义输入框聚焦

export default {
  inserted(el, binding, vnode) {
    el.querySelector('input').focus()
    vnode.componentInstance.openMenu()
   
  },
}
const install = function (Vue) {
  Vue.directive('hasRole', hasRole)
  Vue.directive('hasPermi', hasPermi)
  Vue.directive('reClick', reClick)
  Vue.directive('tableFit', tableFit)
  Vue.directive('myFocus', myFocus)
}

if (window.Vue) {
  window['myFocus'] = myFocus
  Vue.use(install) 
}

export default install

在需要的页面直接使用 v-my-focus就行

<TreeSelect
                              ref="treeRef"                            
                              v-model="row.Code"
                              :options="deptOptions"
                              :normalizer="normalizer"
                              clearable
                              v-my-focus                            
                              loadingText="数据加载中"
                              :matchKeys="['name', 'code']"
                              placeholder=""
                              style="width: 100%"
                              :appendToBody="true"
                              :disable-branch-nodes="true"
                              open-direction="bottom"
                              @select="node => treeHandleSelect(row, rowIndex, node)"
                              @input="value => treeSelectInput(rowIndex, value)"
                          
                            >
                              <div slot="option-label" slot-scope="{ node }" :style="{ marginLeft: !node.raw.children ? '16px' : '0' }">
                                [{{ node.raw.code }}]{{ node.raw.label }}
                              </div>
                              <div slot="value-label" slot-scope="{ node }">{{ row.Code ? `[${row.Code}]` : '' }}{{ row.Name }}</div>
                            </TreeSelect>

openMenu方法我是在源码里找到的,去GitHub上搜vue-treeselect就能看到源码

element ui Switch 开关如何在table中使用 element ui select 插槽_vue.js_02


element ui Switch 开关如何在table中使用 element ui select 插槽_vue.js_03


element ui Switch 开关如何在table中使用 element ui select 插槽_插槽_04

记录下思路,以后也不怕源码了

-------更新-----
早上来点击的时候发现了一个新的bug
就是树下拉框打开选完节点后,它没有自动关上,一直展示着
我本来是想在树节点点击事件里关闭,但是不起作用
看来还是要自定义指令关了
新增myBlur.js

import Vue from 'vue'
//自定义输入框关闭下拉框

export default {
  componentUpdated(el, binding, vnode) {
    if (el.querySelector('input').blur()) {
      setTimeout(() => {
        vnode.componentInstance.closeMenu()
       
      }, 0)
    }
  },
}

首先要判断是否失去焦点,用instrted还是componentUpdated钩子函数,这个我没测试,在试的过程中发现,如果没有定时器,可能会同时执行,也有可能是因为一开始没有写判断条件,反正都可以自己试试,我的已经实现了,就懒得再测了