欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue.js?Table?組件自定義列寬實(shí)現(xiàn)核心方法

 更新時(shí)間:2022年07月25日 10:52:39   作者:??木亦Sam?  
這篇文章主要介紹了vue.js?Table?組件自定義列寬實(shí)現(xiàn)核心方法,文圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下

前言

如果你使用過(guò)類似于 ElementUI 的組件庫(kù),一定對(duì)如下的 API 屬性不眼生,例如:

<!-- Element UI -->
<el-table-column prop="date" label="日期" min-width="150"></el-table-column>
<el-table-column prop="name" label="姓名" width="200"></el-table-column>
<el-table-column prop="province" label="省份" width="200"></el-table-column>

<!-- and-design for vue -->
 cols: [
    { title: '日期',dataIndex: 'date',key: 'date', minWidth: 150 },
    { title: '姓名',dataIndex: 'name',key: 'name', width: 200 },
    { title: '省份',dataIndex: 'province',key: 'province', width: 200 },
],

上面的例子中,Table 組件支持自定義最小寬度min-width和固定寬度width,如果不設(shè)置,則默認(rèn)填充剩余寬度。

如果你打算自己手動(dòng)實(shí)現(xiàn)一個(gè) Table 組件,并且對(duì)支持定義列寬屬性的實(shí)現(xiàn)毫無(wú)頭緒,那這篇文章大概率可以幫你梳理一些邏輯和核心方法的實(shí)現(xiàn)(Vue3)

注:這也許不是最佳的實(shí)現(xiàn)方案。

準(zhǔn)備工作:

這里假定使用的是類似于and-design for vue的屬性傳值方式,即列的屬性配置是通過(guò)額外的數(shù)組對(duì)象傳入的。

除了title-列表頭名,key-列值對(duì)應(yīng)的鍵外,還有這篇文章涉及到的最小寬度minWidth和固定寬度width,并通過(guò)組件屬性cols傳入。

colgroup 和 col

這里需要用到<colgroup><col>標(biāo)簽,以便更好的去控制每列的屬性信息,兩個(gè)標(biāo)簽均支持傳入width屬性控制列寬度,不同的是,<col>控制的是單列的寬度,而<colgroup>可以控制所包含在內(nèi)的。

除此之外,這兩個(gè)標(biāo)簽還有如下注意事項(xiàng):

  • colgroup需在 table 標(biāo)簽中
  • col需在 colgroup 標(biāo)簽中,且只能包含 標(biāo)簽
  • 兩者均無(wú)法為表格創(chuàng)建列,僅控制列的展現(xiàn)形式
  • 在 xhtml 中,col必須含有結(jié)束標(biāo)簽

根據(jù)我們的需求,我們需要單獨(dú)控制每一列的寬度展示,并在瀏覽器寬度變化時(shí)實(shí)時(shí)的重新計(jì)算并且重新渲染列。

大致的功能如下:

  • 含有width的列,寬度固定,不隨瀏覽器寬度變化而變化
  • 含有minWidth的列,在大于設(shè)定值時(shí),自動(dòng)填充 table 剩余寬度,小于設(shè)定值時(shí),固定該寬度
  • 不包含widthminWidth的列,自動(dòng)填充 table 剩余寬度

最終實(shí)現(xiàn)如下渲染效果:

<template>
    <colgroup>
        <col
         v-for="(item, index) in columns"
         :key="`table-tr-${index}`"
         :name="`table_tr_${index}`"
         :width="`${item.width}px`"
         />
    </colgroup>
</template>

核心實(shí)現(xiàn)

一些常量/變量定義

在 Table 組件初始化的時(shí)候,需要定義一些變量以供后續(xù)方法中使用,具體如下:

/** Table 實(shí)例 */
const bpTable = ref(null);

/** 最終用于渲染的 columns 表頭列表 */
const columns = ref([]);

/** 表格所占的實(shí)際寬度 px */
const _table_width = ref("");

/** 在沒(méi)有設(shè)定寬度時(shí),可用于撐開(kāi)剩余寬度的列數(shù) */
let _remainder_col = 0;

/** 固定寬度(包含自定義的寬和最小寬的總和) */
let _fixed_width = 0;

/** 各列最小寬度數(shù)組 */
let _min_width_list = [];

/** 表格各列寬度數(shù)組 */
let _col_width_list = [];

/** 單列最小寬度 */
const _min_column_width = 80;

初始化表頭列表 initColumns

在表格整體渲染結(jié)束,能獲取 table 實(shí)際寬度后,需要執(zhí)行表頭列表初始化,對(duì)傳入的props中的cols進(jìn)行處理,計(jì)算實(shí)際每一列需要width值。

/**
 * 初始化表頭列表
 * @returns Array
 */
const initColumns = () => {
    const el = bpTable.value;
    const { cols } = props;

    /** 每次需要初始化的一些值 */
    _fixed_width = 0;
    _remainder_col = cols.length;
    _min_width_list = [];

    // 1. 處理含有固定寬度和最小寬的列

    // 2. 獲取各列寬度,并組成一個(gè)數(shù)組

        // 計(jì)算需要自適應(yīng)的列寬度

    // 3. 輸出 columns
}

處理含有固定寬度和最小寬的列

如果含有自定義的寬和最小寬,則需要單獨(dú)處理這些列,使其不參與剩余寬度自適應(yīng)當(dāng)中,同時(shí)對(duì)應(yīng)的自適應(yīng)列的數(shù)量也要相應(yīng)的減去,處理邏輯如下:

for (let i = 0; i < cols.length; i++) {
    const { width, minWidth } = cols[i];

    if (width) {
            _fixed_width += Number(width);
            _remainder_col--;
    }
    minWidth && _min_width_list.push(minWidth)
}

獲取各列寬度,并組成一個(gè)數(shù)組 getWidthList

這個(gè)方法目的返回一個(gè)數(shù)組,包含各列的寬度值,最后匹配到columns中。 為了不出現(xiàn)列寬過(guò)于太小而把內(nèi)容擠掉的情況,需要判斷最小值不能小于設(shè)定的80px

/**
 * 獲取各列寬度,并組成一個(gè)數(shù)組
 * @returns Array width_list
 */
function getWidthList() {
    const { cols } = props;
    /** 各列寬度數(shù)組 */
    let width_list = [];
    /** 自適應(yīng)列寬 */
    let adapt_width = getAdaptWidth();
    /**
    * 當(dāng)表格中含有設(shè)置最小寬度的列時(shí),需要挨個(gè)比較自適應(yīng)寬是否小于最小寬度
    * 如果小于,則重新設(shè)置各個(gè)值并重新計(jì)算自適應(yīng)寬度
    */
    if (_min_width_list.length) {
        _min_width_list.map((item, index) => {
            if (adapt_width > item) {
                _fixed_width += item;
                _remainder_col--;
                _min_width_list.splice(index, 1);
                adapt_width = getAdaptWidth();
            }
        });
    }

    for (let i = 0; i < cols.length; i++) {
        const { width, minWidth } = cols[i];

        // 設(shè)置成固定寬度
        if (width) { width_list.push(width); continue; }

        // 是否設(shè)置成最小寬度:當(dāng)含有最小寬度屬性并且最小寬度大于計(jì)算得出的最大列寬
        const hasMinWidth = minWidth && minWidth > adapt_width;
        if (hasMinWidth) { width_list.push(minWidth); continue; }

        // 如果沒(méi)有定義寬度和最小寬,則設(shè)置成自適應(yīng)寬度或者最小預(yù)設(shè)寬度
        width_list.push(adapt_width < _min_column_width ? _min_column_width : adapt_width);
    }
    return width_list;
}

計(jì)算需要自適應(yīng)的列寬度 getAdaptWidth

在表格整體渲染結(jié)束,能獲取 table 實(shí)際寬度后,需要計(jì)算允許列自適應(yīng)的寬度有多少,如果所有列都沒(méi)有設(shè)置寬度值,這時(shí)候自適應(yīng)的列寬即為 table 的實(shí)際寬度,列寬平均分布就行了。

/**
    * 根據(jù)表格實(shí)際寬度、已固定的列寬、以及剩余自適應(yīng)列數(shù),計(jì)算得出自適應(yīng)列寬
    * @returns Number width
    */
    function getAdaptWidth() {
    let width = (_table_width.value - _fixed_width) / _remainder_col;
    return Number(width).toFixed(2);
    }
    ```
    #### 完整代碼
    ```javascript
    /**
    * 獲取各列寬度,并組成一個(gè)數(shù)組
    * @returns Array width_list
    */
    function getWidthList() {
    const { cols } = props;

    /** 各列寬度數(shù)組 */
    let width_list = [];

    /** 自適應(yīng)列寬 */
    let adapt_width = getAdaptWidth();

    /**
     * 當(dāng)表格中含有設(shè)置最小寬度的列時(shí),需要挨個(gè)比較自適應(yīng)寬是否小于最小寬度
     * 如果小于,則重新設(shè)置各個(gè)值并重新計(jì)算自適應(yīng)寬度
     */
    if (_min_width_list.length) {
      _min_width_list.map((item, index) => {
        if (adapt_width > item) {
          _fixed_width += item;
          _remainder_col--;
          _min_width_list.splice(index, 1);
          adapt_width = getAdaptWidth();
        }
      });
    }

    for (let i = 0; i < cols.length; i++) {
      const { width, minWidth } = cols[i];

      // 設(shè)置成固定寬度
      if (width) { width_list.push(width); continue; }

      // 是否設(shè)置成最小寬度:當(dāng)含有最小寬度屬性并且最小寬度大于計(jì)算得出的最大列寬
      const hasMinWidth = minWidth && minWidth > adapt_width;
      if (hasMinWidth) { width_list.push(minWidth); continue; }

      // 如果沒(méi)有定義寬度和最小寬,則設(shè)置成自適應(yīng)寬度或者最小預(yù)設(shè)寬度
      width_list.push(adapt_width < _min_column_width ? _min_column_width : adapt_width);
    }
    return width_list;
    }

監(jiān)聽(tīng)屏幕變化和屬性更新

觸發(fā)initColumns的時(shí)機(jī)有三個(gè)

  • 初次加載表格組件
  • 列屬性有更新時(shí)
  • 屏幕寬度變化時(shí)
  watch(() => props.cols, () => { initColumns() });

  onMounted(() => {
    nextTick(() => {
      initColumns();
      on(window, 'resize', throttle(() => initColumns(), 400));
    });
  });
  onBeforeUnmount(() => off(window, 'resize', () => initColumns()));

到此這篇關(guān)于vue.js Table 組件自定義列寬實(shí)現(xiàn)核心方法的文章就介紹到這了,更多相關(guān)vue.js Table 組件自定義內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論