使ElementUI的el-table表頭自動吸頂缴守,支持左右固定列

背景

在使用el-table的時候葬毫,在數(shù)據(jù)多的情況下滾動表格會看不到表頭是什么,可以使用高度自適應(yīng)屡穗,這是對表格高度的限制同時會出現(xiàn)滾動條贴捡,這樣用戶體驗不好,所以考慮不設(shè)置高度通過表頭吸頂來實現(xiàn)村砂。

思路

網(wǎng)上也有一些解決方案寫了一大堆代碼栈暇。很麻煩。(os:我沒成功過)

我研究了el-tabledom結(jié)構(gòu)箍镜,發(fā)現(xiàn)其實只需要少量簡單的計算去修改樣式就可以達(dá)到效果源祈。

主要還是使用CSS屬性position: sticky

注意

由于使用的是sticky,所以要保證祖先元素不能設(shè)置overflow:hidden這類的樣式色迂,否則不生效香缺。

效果

1.gif

2.gif

使用

v-tableSticky使用文檔

import {tableSticky} from 'lp-vue'
Vue.directive('tableSticky', tableSticky)

實現(xiàn)

為了方便使用,把表頭吸頂寫成一個方法歇僧,最后在指令里調(diào)用即可图张。

  1. 吸頂高度確認(rèn)

指令什么都不傳默認(rèn)吸頂高度為0锋拖,可以傳遞具體的吸頂高度值(數(shù)字),可以傳遞可以獲取到dom的選擇器名

const stickyThead = (el, binging, vnode) => {
    let top = "0px";
    //如果是吸頂高度
    if (!isNaN(Number(binging.value))) {
        top = binging.value + "px";
    }
    //如果是選擇器名
    if (typeof binging.value === "string") {
        let rect = document.querySelector(binging.value)?.getBoundingClientRect();
        top = rect ? rect.top + rect.height + "px" : "0px";
    }
}
  1. 頭部吸頂
el.style.overflow = "visible";
const tHeader = el.querySelector(".el-table__header-wrapper");
tHeader.style.position = "sticky";
tHeader.style.top = top;
tHeader.style.zIndex = 10;

到這里基本上已經(jīng)實現(xiàn)表頭吸頂?shù)墓δ芰嘶雎郑侨绻霈F(xiàn)固定列的話就不行兽埃。那么繼續(xù)完善。

研究表格元素結(jié)構(gòu)發(fā)現(xiàn)适袜,沒有固定列的頭部在el-table__header-wrapper柄错,而有固定列的頭部會被額外拆分到el-table__fixedel-table__fixed-right苦酱, 其實可以直接修改el-table__header-wrapper里面的th樣式即可售貌。

  1. 去除is-hidden

需要把th中的is-hidden這個類名刪除,才會顯示固定列的頭

const ths = tHeader.querySelectorAll("th.is-hidden");
ths.forEach((item) => {
    item.classList.remove("is-hidden");
});
  1. 固定列吸頂
// 找到實例
const table = vnode.context.$children.find((item) => item.$el === el);
// 找到左邊固定列的信息
const leftFixed = table.fixedColumns;
if (leftFixed && leftFixed.length) {
    let leftFixedWidth = 0;
    leftFixed.forEach((item) => {
        let itemW = item.width || item.realWidth || item.minWidth;
        const cell = tHeader.querySelector("th." + item.id);
        if (cell) {
            cell.style.position = "sticky";
            cell.style.left = leftFixedWidth + "px";
            cell.style.top = top;
            cell.style.zIndex = 10;
            leftFixedWidth += itemW;
        }
    });
}

// 找到右邊固定列
const rightFixed = table.rightFixedColumns;
if (rightFixed && rightFixed.length) {
    let rightFixedWidth = 0;
    for (let i = rightFixed.length - 1; i >= 0; i--) {
        let itemW = rightFixed[i].width || rightFixed[i].realWidth || rightFixed[i].minWidth;
      const cell = tHeader.querySelector("th." + rightFixed[i].id);
      if (cell) {
        cell.style.position = "sticky";
        cell.style.right = rightFixedWidth + "px";
        cell.style.top = top;
        cell.style.zIndex = 10;
        rightFixedWidth += itemW;
      }
    }
  }
};

細(xì)節(jié): 右邊的固定列要倒著設(shè)置

  1. 指令調(diào)用時機
var tableOb = null;
var domOb = null;
export default {
  inserted(el, binging, vnode) {
    //監(jiān)聽表格變化
    tableOb = new ResizeObserver(() => {
      stickyThead(el, binging, vnode);
    });
    tableOb.observe(el);

    // 監(jiān)聽目標(biāo)dom變化
    if (typeof binging.value === "string") {
      let isDom = document.querySelector(binging.value);
      if (isDom) {
        domOb = new ResizeObserver(() => {
          stickyThead(el, binging, vnode);
        });
        domOb.observe(isDom);
      }
    }
  },
  unbind(el, binging, vnode) {
    tableOb && tableOb.unobserve(el);
    if (typeof binging.value === "string") {
      let isDom = document.querySelector(binging.value);
      if (isDom) {
        domOb && domOb.unobserve(el);
      }
    }
  },
};
  • 思考一:表格監(jiān)聽

表格插入到頁面的時候要監(jiān)聽表格的變化疫萤,從而調(diào)用這個方法颂跨,這個監(jiān)聽是必要的,能夠在表格變化的時候重新計算位置扯饶。(考慮左右位置的計算)

  • 思考二:目標(biāo)元素監(jiān)聽

在使用目標(biāo)元素來決定吸頂高度時恒削,隨著頁面的變化可能目標(biāo)元素的高度會變高,那就有必要重新調(diào)用這個方法尾序,如果高度固定就不需要監(jiān)聽蔓同;或者目標(biāo)元素的寬小于等于表格的寬度,這樣頁面變化會觸發(fā)表格的監(jiān)聽同樣不需要這個監(jiān)聽蹲诀。所以這個監(jiān)聽不是必要的。主要關(guān)注點還是在stickyThead這個方法上弃揽,剩下的就是觸發(fā)時機脯爪。(考慮吸頂?shù)奈恢茫?/p>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市矿微,隨后出現(xiàn)的幾起案子痕慢,更是在濱河造成了極大的恐慌,老刑警劉巖涌矢,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件掖举,死亡現(xiàn)場離奇詭異,居然都是意外死亡娜庇,警方通過查閱死者的電腦和手機塔次,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來名秀,“玉大人励负,你說我怎么就攤上這事∝暗茫” “怎么了继榆?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我略吨,道長集币,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任翠忠,我火速辦了婚禮鞠苟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘负间。我一直安慰自己偶妖,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布政溃。 她就那樣靜靜地躺著趾访,像睡著了一般。 火紅的嫁衣襯著肌膚如雪董虱。 梳的紋絲不亂的頭發(fā)上扼鞋,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天,我揣著相機與錄音愤诱,去河邊找鬼云头。 笑死,一個胖子當(dāng)著我的面吹牛淫半,可吹牛的內(nèi)容都是我干的溃槐。 我是一名探鬼主播,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼科吭,長吁一口氣:“原來是場噩夢啊……” “哼昏滴!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起对人,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤谣殊,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后牺弄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體姻几,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年势告,在試婚紗的時候發(fā)現(xiàn)自己被綠了蛇捌。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡咱台,死狀恐怖豁陆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情吵护,我是刑警寧澤盒音,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布表鳍,位于F島的核電站,受9級特大地震影響祥诽,放射性物質(zhì)發(fā)生泄漏譬圣。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一雄坪、第九天 我趴在偏房一處隱蔽的房頂上張望厘熟。 院中可真熱鬧,春花似錦维哈、人聲如沸绳姨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽飘庄。三九已至,卻和暖如春购撼,著一層夾襖步出監(jiān)牢的瞬間跪削,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工迂求, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留碾盐,地道東北人。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓揩局,卻偏偏與公主長得像毫玖,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子凌盯,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,960評論 2 355

推薦閱讀更多精彩內(nèi)容