解决elementUI Select multiple 抖动问题,复制并重写elementUI中Select源码函数,全局配置Select的filterable属性
问题
- 问题: 项目中出现 el-select 设置了 multiple ,多选tag后,在将页面放大或缩小时,el-selet中的el-input的高度一直在抖动,
bug定位
- 定位: 在elment源码中,在
node_modules/element-ui/packages/select/src/select.vue文件下的第644行存在一个resetInputHeight函数,该函数被我重写后打印发现上图的tags.clientHeight的获取每次获取都不一致,在85和84之间跳动,导致页面抖动
解决
- 解决: 复制并修改 element-ui 中 select 的
resetInputHeight函数,利用getBoundingClientRect()函数,获取指定 dom 的具体高度,然后直接添加到 heitht (浏览器会自动将height识别为一个整数)- 添加
elementUi.js文件,在 main.js 文件中引入 element-ui 之后 使用Vue.use(elementUi)的方法实现重写 - 顺路配置了全局 select 的 filterable 属性
- 添加
import ElementUI from 'element-ui'
let elementUiComponent = {}
elementUiComponent.install = function (Vue) {
// const seletRender = ElementUI.Select.render
// ElementUI.Select.render = function () {
// 重写select渲染方法,看情况使用-添加渲染时操作
// return seletRender.apply(this, arguments)
// }
// 全局统一添加 filterable 默认传参,可被组件使用时的 filterable 属性覆盖
ElementUI.Select.props.filterable = { type: Boolean, default: true }
// 全局select直接修改
// TODO:如果el-select 多选还会导致页面抖动,则使用这个方法重写,并删除 .el-select .el-tag--mini 自定义样式配置和 --el-tag-height css变量配置
ElementUI.Select.methods.resetInputHeight = function () {
// 重写tag高度判定
if (this.collapseTags && !this.filterable) return
this.$nextTick(() => {
if (!this.$refs.reference) return
let inputChildNodes = this.$refs.reference.$el.childNodes
let input = [].filter.call(inputChildNodes, (item) => item.tagName === 'INPUT')[0]
const tags = this.$refs.tags
// element 使用 clientHeight 计算高度,但是在某些情况下,会出现高度不一致的情况,所以这里使用 getBoundingClientRect 计算高度
const tagsRect = tags ? tags.getBoundingClientRect() : null
const sizeInMap = this.initialInputHeight || 40
input.style.height =
this.selected.length === 0
? sizeInMap + 'px'
: // 备份element-ui的原代码
// Math.max(tags ? tags.clientHeight + (tags.clientHeight > sizeInMap ? 6 : 0) : 0, sizeInMap) + 'px'
Math.max(tags ? tagsRect.height + (tagsRect.height > sizeInMap ? 6 : 0) : 0, sizeInMap) + 'px'
// console.log('el-input__inner height -->', input.style.height, 'tags.clientHeight -->', tags.clientHeight)
if (this.visible && this.emptyText !== false) {
this.broadcast('ElSelectDropdown', 'updatePopper')
}
})
}
}
export default elementUiComponent
- main.js 中文件使用
// main.js
...
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
...
import elementUiComponent from '@/plugins/elementUi.js'
Vue.use(elementUiComponent)
后话
也可以看看另一个大佬的文章提到修改tag高度和tag的margin方法,如果可以的话也不用我这样麻烦(我没成功,测试太严谨了,各种比列看抖动) 文章:解决elementUI multiple Select 抖动问题