亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

前言

如果你使用過類似于 ElementUI 的組件庫,一定對如下的 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)填充剩余寬度。

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

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

準(zhǔn)備工作:

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

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

colgroup 和 col

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

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

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

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

大致的功能如下:

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

最終實現(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>

核心實現(xiàn)

一些常量/變量定義

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

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

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

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

/** 在沒有設(shè)定寬度時,可用于撐開剩余寬度的列數(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 實際寬度后,需要執(zhí)行表頭列表初始化,對傳入的props中的cols進(jìn)行處理,計算實際每一列需要width值。

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

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

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

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

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

    // 3. 輸出 columns
}

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

如果含有自定義的寬和最小寬,則需要單獨處理這些列,使其不參與剩余寬度自適應(yīng)當(dāng)中,同時對應(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)
}

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

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

/**
 * 獲取各列寬度,并組成一個數(shù)組
 * @returns Array width_list
 */
function getWidthList() {
    const { cols } = props;
    /** 各列寬度數(shù)組 */
    let width_list = [];
    /** 自適應(yīng)列寬 */
    let adapt_width = getAdaptWidth();
    /**
    * 當(dāng)表格中含有設(shè)置最小寬度的列時,需要挨個比較自適應(yīng)寬是否小于最小寬度
    * 如果小于,則重新設(shè)置各個值并重新計算自適應(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)含有最小寬度屬性并且最小寬度大于計算得出的最大列寬
        const hasMinWidth = minWidth && minWidth > adapt_width;
        if (hasMinWidth) { width_list.push(minWidth); continue; }

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

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

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

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

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

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

    /**
     * 當(dāng)表格中含有設(shè)置最小寬度的列時,需要挨個比較自適應(yīng)寬是否小于最小寬度
     * 如果小于,則重新設(shè)置各個值并重新計算自適應(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)含有最小寬度屬性并且最小寬度大于計算得出的最大列寬
      const hasMinWidth = minWidth && minWidth > adapt_width;
      if (hasMinWidth) { width_list.push(minWidth); continue; }

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

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

觸發(fā)initColumns的時機(jī)有三個

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

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

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

相關(guān)文章

最新評論