Element UI實現(xiàn)表格列寬隨內(nèi)容自適應(yīng)

前言

對于動態(tài)獲取數(shù)據(jù)的表格聚至,如果期望單元格內(nèi)容不折行酷勺,就要設(shè)定足夠的寬度,同時又希望表格內(nèi)容盡量緊湊扳躬,但是脆诉,由于數(shù)據(jù)不確定,所以無法預(yù)設(shè)寬度贷币,怎么辦呢击胜?有這樣一種辦法:

方案

  1. 先讓表格渲染
  2. 引入CSS class來讓單元格內(nèi)容單行顯示
  3. 遍歷表體的.cell,算出每個元素的scrollWidth片择,匯總到二維數(shù)組里
  4. 考察二維數(shù)組的每個一級元素的每個單元格的寬度潜的,找出最大值
  5. <el-table-column>設(shè)置的width都等于各自列的最大值即可

這個方案按理說,會發(fā)生表格閃爍字管,因為先渲染啰挪,又調(diào)整列寬的緣故。為了解決這個問題嘲叔,我想到了visibility: hidden;亡呵,當(dāng)hidden時,表格依然會渲染硫戈,只不過不顯示锰什,此時就可以計算各種寬度,等計算好,賦值好汁胆,再visible即可梭姓。

恰好可以借用loading變量實現(xiàn)hiddenvisible的切換。

template

  1. 給表格組件加上這個:
ref="listTable" class="columns-fit" :class="loading ? null : 'visible'"
  1. 給每個<el-table-column>加上width嫩码,如下:
      <el-table-column type="selection" align="center" :width="colWidthList[0]" />
      <el-table-column label="序號" align="center" prop="id" :width="colWidthList[1]" />
      ...
      ...

其中下標(biāo)表示第幾個列誉尖。你可以給有些列不設(shè)width,或者設(shè)置固定數(shù)值铸题,此時其他列的下標(biāo)無需調(diào)整铡恕,但是如果列順序變了,下標(biāo)必須重排丢间。

style

在某個全局引入的scss文件寫入:

.columns-fit {
  .el-table__header-wrapper, .el-table__body-wrapper {
    visibility: hidden;
  }

  &.visible {
    .el-table__header-wrapper, .el-table__body-wrapper {
      visibility: visible;
    }
  }

  .el-table__body-wrapper {
    overflow: auto;
  }

  td>.cell {
    display: inline-block;
    white-space: nowrap;
    width: auto;
    overflow: auto;
  }
}

script

先不說本方案探熔,先說原始的請求數(shù)據(jù)列表的代碼大致是這樣:

    getList() {
      this.loading = true;
      list(this.queryParams).then(response => {
        this.list = response.data;
        this.total = response.total;
        this.loading = false;
      });
    },

然后我們對它略改造,加上一句:

    getList() {
      this.loading = true;
      list(this.queryParams).then(response => {
        this.list = response.data;
        this.total = response.total;
        this.$nextTick(() => {
          setTimeout(() => {
            this.colWidthList = this.$adjustColumnWidth(this.$refs['listTable'].$el);
            this.loading = false;
          });
        });
      });
    },

colWidthListdata里定義一個空數(shù)組烘挫,用來存每個col的最終寬度诀艰。

比較迷的是setTimeout,你是不是不知道我為啥加一句這個墙牌?當(dāng)表格沒有橫向滾動條涡驮,用下方的代碼計算出來的每個單元格的scrollWidth會有錯誤暗甥,原因是Element UI的某些計算規(guī)則比較迷喜滨,它先計算一遍,然后微調(diào)一遍撤防,會讓單元格稍微變化幾像素虽风,而setTimeout從JS底層說是宏任務(wù),可以等待Element UI對單元格的調(diào)整結(jié)束寄月,這樣辜膝,得到的scrollWidth才是準(zhǔn)的。

adjustColumnWidth函數(shù)需要寫入一個全局JS:

export default function(el) {
  let widthList = [];

  el.querySelectorAll('.el-table__body tr').forEach((tr) => {
    tr.querySelectorAll('td').forEach((td, i) => {
      if (!widthList[i]) {
        widthList[i] = [];
      }
      widthList[i].push(td.scrollWidth);
    });
  });

  return widthList.map(width => Math.max(...width));
}

main.js里引入:

import adjustColumnWidth from '@/utils/adjustColumnWidth';
Vue.prototype.$adjustColumnWidth = adjustColumnWidth;

到此OK漾肮。

使用特別說明

1. 本方案不考慮表頭的單元格溢出厂抖,請另外考慮

image.png

Element UI里面有這樣的樣式,其中由于text-overflow的值沒有none克懊,也就是說忱辅,text-overflow一旦寫上了就無法取消,導(dǎo)致表頭無法像表身一樣呈現(xiàn)單行且無省略號的狀態(tài)谭溉,因此也就無法取得我們想要的表頭單元格的scrollWidth墙懂,所以,本方案不計算表頭單元格的寬度扮念。這就導(dǎo)致了一個問題:

如果某列的表頭字符很長损搬,但表身內(nèi)容很短,這樣計算得到的width會比表頭字符還要短,表頭會出現(xiàn)折行巧勤。

結(jié)論:要么嵌灰,你就接受這種折行的設(shè)定,要么颅悉,就給col寫死固定的伞鲫、足夠的width值。

2. 刪除列签舞、調(diào)整列順序時秕脓,:width="colWidthList[n]"的下標(biāo)要記得對應(yīng)修改

請記得對應(yīng)修改。下標(biāo)應(yīng)該永遠(yuǎn)是列的排序序號儒搭。

3. 瀏覽器窗口由小窗拉大到大窗吠架,表格寬度不變,右側(cè)出現(xiàn)空白搂鲫,怎么解決傍药?

首先說,width屬性是Element UI官方屬性魂仍,如果全部列都設(shè)置了width拐辽,那么官方也沒有辦法讓表格自適應(yīng)容器寬度,所以這其實并不是本方案的鍋擦酌。

我這里提個解決方案:

監(jiān)聽window.onsize俱诸,動態(tài)修改colWidthList,等比放大赊舶,代碼我就不寫了睁搭,因為本身這個需求就是極小概率出現(xiàn)的需求。

4. 不要給所有表格都用本方案

如果表格明顯內(nèi)容稀松笼平,就堅決不要使用本方案园骆,因為沒必要。

5. 不要給所有列都用本方案

假如某列的內(nèi)容忽長忽短寓调,短的只有幾個字锌唾,長的有50個字,那么這一列顯然不適合使用自適應(yīng)列寬夺英,因為會造成大面積的空白晌涕,請給該列鎖定width

6. 本方案的缺點

本方案為了不讓表格抖動秋麸,造成了2個負(fù)面效果:

  1. 會讓表格消失幾十到幾百毫秒甚至幾秒渐排,根據(jù)ajax請求速度而定。如果不采用本方案灸蟆,表格只是被loading遮罩遮住幾十到幾百毫秒至幾秒驯耻,而且遮罩往往半透明亲族,能看到表格的隱約內(nèi)容,是一種具有“高級感”的設(shè)計可缚。

  2. 設(shè)置width會導(dǎo)致大規(guī)模的UI回流和重繪霎迫,頁面會非常輕微、不易覺察的卡頓一下帘靡,不過好在Element UI做政企系統(tǒng)多知给,可以強迫用戶使用現(xiàn)代瀏覽器,所以問題很輕微描姚。

總之涩赢,如果需求方對界面美觀比較在意,對輕微的轩勘、不易察覺的卡頓不太在乎筒扒,那么可以考慮本方案,如果追求極致流暢绊寻,則請不要使用本方案花墩。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市澄步,隨后出現(xiàn)的幾起案子冰蘑,更是在濱河造成了極大的恐慌,老刑警劉巖村缸,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件祠肥,死亡現(xiàn)場離奇詭異,居然都是意外死亡王凑,警方通過查閱死者的電腦和手機搪柑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進(jìn)店門聋丝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來索烹,“玉大人,你說我怎么就攤上這事弱睦“傩眨” “怎么了?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵况木,是天一觀的道長垒拢。 經(jīng)常有香客問我,道長火惊,這世上最難降的妖魔是什么求类? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮屹耐,結(jié)果婚禮上尸疆,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好寿弱,可當(dāng)我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布犯眠。 她就那樣靜靜地躺著,像睡著了一般症革。 火紅的嫁衣襯著肌膚如雪筐咧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天噪矛,我揣著相機與錄音量蕊,去河邊找鬼。 笑死艇挨,一個胖子當(dāng)著我的面吹牛危融,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播雷袋,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼吉殃,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了楷怒?” 一聲冷哼從身側(cè)響起蛋勺,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鸠删,沒想到半個月后抱完,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡刃泡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年巧娱,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片烘贴。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡禁添,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出桨踪,到底是詐尸還是另有隱情老翘,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布锻离,位于F島的核電站铺峭,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏汽纠。R本人自食惡果不足惜卫键,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望虱朵。 院中可真熱鬧莉炉,春花似錦啤呼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至羞福,卻和暖如春惕蹄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背治专。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工卖陵, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人张峰。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓泪蔫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親喘批。 傳聞我的和親對象是個殘疾皇子撩荣,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,802評論 2 345