本來(lái)想在 jsfiddle 重現(xiàn)下的,結(jié)果沒(méi)有成功,就給大家看截圖吧
vue版本:2.5.3
element-ui版本:1.4.13
瀏覽器:chrome 66.0.3359.170
大家可以發(fā)現(xiàn),固定了高度的 table 不僅出現(xiàn)了縱向滾動(dòng)條,橫向滾動(dòng)條也出現(xiàn)了(只能滾動(dòng)一點(diǎn)點(diǎn)),其實(shí)寬度是足夠顯示的。
然后將問(wèn)題在網(wǎng)上搜尋,查到了相關(guān)的issues
https://github.com/ElemeFE/element/issues/2945
https://github.com/ElemeFE/element/issues/78
其中#78的問(wèn)答者給出了一個(gè)解決方案https://github.com/QingWei-Li/element/commit/a019e57da9f6271d120e04c67ab330c4f48e56c6
有一點(diǎn)和#78相似,我的 table 也是配置化的,表頭和內(nèi)容都是作為屬性傳過(guò)去,可能導(dǎo)致表格在初次渲染時(shí)寬度計(jì)算不準(zhǔn)確,導(dǎo)致最后寬度超過(guò)了 2px(經(jīng)查驗(yàn)是 border 的寬度);但解決方案不適用,一方面項(xiàng)目采用的是 cdn 加載方式,另一方面我嘗試了 1.4.13 版本和解決方案的 1.0.1 版本代碼結(jié)構(gòu)不一致,而我對(duì) element 組件不了解無(wú)從下手,所以我嘗試自己去解決。
先貼上我配置化table的代碼,便于后面查閱
<template>
<div>
<el-table border :data="data" height="550" v-loading="isLoading">
<el-table-column v-for="{value, label, options} in columns" :key="value" :label="label" :prop="value">
<template slot-scope="{row}">
<span v-if="!options">{{row[value]}}</span>
<div v-else-if="options && options.filter">{{row[value] | filterData(options.filter)}}</div>
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="{row}">
<!--這里可在父級(jí)插入自定義操作按鈕-->
<slot :row="row"/>
</template>
</el-table-column>
</el-table>
<Pagination :total="total" @fetchData="$emit('fetchData')"/>
</div>
</template>
<script>
import Pagination from 'FORM/Pagination'
import {formatTimestamp} from 'UTILS'
export default {
props: {
isLoading: {
type: Boolean,
default: false,
required: true
},
columns: {
type: Array,
default: [],
required: true
},
data: {
type: Array,
default: [],
required: true
},
total: {
type: Number,
default: 0,
required: true
}
},
components: {
Pagination
},
filters: {
filterData: function (value, filter) {
if (!filter) return value
switch (filter) {
case 'formatDate':
return formatTimestamp(value)
break;
default:
return value
}
}
}
}
</script>
方案一:嘗試在渲染后修改數(shù)據(jù)讓table重繪
在配置化組件的updated鉤子更新 columns 數(shù)據(jù)(中間做了一層轉(zhuǎn)換,沒(méi)有直接修改 props ),但 table 貌似不會(huì)將數(shù)據(jù)進(jìn)行雙向綁定(這方面不確定,只是我調(diào)試時(shí)修改 table 的內(nèi)容不能實(shí)時(shí)更新,需要刷新瀏覽器),所以 table 沒(méi)有出現(xiàn)改變,也就不會(huì)觸發(fā)第二次寬度計(jì)算。
方案二:嘗試在渲染后將2px的border去掉
在瀏覽器中調(diào)試發(fā)現(xiàn)去掉.el-table的左右 border 后,是可以解決內(nèi)容溢出產(chǎn)生滾動(dòng)條的問(wèn)題的;具體做法是在 updated 1s后給el-table綁定一個(gè) class,去除 border,但沒(méi)有 border 太不美觀了。。。
方案三:將寬度計(jì)算交給瀏覽器
也是在瀏覽器中調(diào)試,發(fā)現(xiàn)將.el-table__body-wrapper的overflow屬性隱藏再顯示,橫向滾動(dòng)條就不會(huì)出現(xiàn)了,應(yīng)該是重新添加overflow: auto;使得瀏覽器自身重新計(jì)算了 table 的寬度,所以寬度足夠的情況下不需要顯示橫向滾動(dòng)條;
那做法就是:
<!-- template -->
<el-table ref="configurationTable" border :data="data" :height="height" v-loading="isLoading" :class="['configurationTable', {afterRenderClass: showAfterRenderClass}]">
<!-- xxx -->
</el-table>
// script
data () {
return {
showAfterRenderClass: false
}
},
updated () {
/**
* 用于隱藏固定高度時(shí)顯示不必要的scrollX的定時(shí)器
* 這是el-table初次渲染時(shí)寬度計(jì)算的bug,可在渲染后通過(guò)重新賦予overflow: auto調(diào)整
*/
const handleScrollX = setInterval(() => {
// 檢測(cè)是否已經(jīng)生成table節(jié)點(diǎn),如果不是就每隔0.5s檢測(cè)一次
// 只有生成了真實(shí)節(jié)點(diǎn)才能夠通過(guò)修改overflow屬性讓瀏覽器重新計(jì)算
if (this.$refs.configurationTable) {
this.showAfterRenderClass = true
clearInterval(handleScrollX)
}
}, 500)
}
/** style (注意不要設(shè)為scoped) */
/** configurationTable和afterRenderClass都是為了標(biāo)記僅這個(gè)組件內(nèi)修改 */
.configurationTable .el-table__body-wrapper {
overflow: hidden;
}
.afterRenderClass {
.el-table__body-wrapper {
overflow: auto;
}
}
總結(jié)
因?yàn)閑lement-ui v1已經(jīng)停止維護(hù)了,所以也就不提新的issue了,之后還是需要遷移到element-ui2(如果大家有遷移工具的話歡迎推薦,官方踩過(guò)坑也可以推薦),不然留下這個(gè)黑魔法增加維護(hù)成本。