前言

如果你使用过类似于 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,如果不设置,则默认填充剩余宽度。

如果你打算自己手动实现一个 Table 组件,并且对支持定义列宽属性的实现毫无头绪,那这篇文章大概率可以帮你梳理一些逻辑和核心方法的实现(Vue3)

注:这也许不是最佳的实现方案。

准备工作:

这里假定使用的是类似于and-design for vue的属性传值方式,即列的属性配置是通过额外的数组对象传入的。

除了title-列表头名,key-列值对应的键外,还有这篇文章涉及到的最小宽度minWidth和固定宽度width,并通过组件属性cols传入。

colgroup 和 col

这里需要用到<colgroup><col>标签,以便更好的去控制每列的属性信息,两个标签均支持传入width属性控制列宽度,不同的是,<col>控制的是单列的宽度,而<colgroup>可以控制所包含在内的。

除此之外,这两个标签还有如下注意事项:

  • colgroup需在 table 标签中
  • col需在 colgroup 标签中,且只能包含 标签
  • 两者均无法为表格创建列,仅控制列的展现形式
  • 在 xhtml 中,col必须含有结束标签

根据我们的需求,我们需要单独控制每一列的宽度展示,并在浏览器宽度变化时实时的重新计算并且重新渲染列。

大致的功能如下:

  • 含有width的列,宽度固定,不随浏览器宽度变化而变化
  • 含有minWidth的列,在大于设定值时,自动填充 table 剩余宽度,小于设定值时,固定该宽度
  • 不包含widthminWidth的列,自动填充 table 剩余宽度

最终实现如下渲染效果:

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

核心实现

一些常量/变量定义

在 Table 组件初始化的时候,需要定义一些变量以供后续方法中使用,具体如下:

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

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

/** 表格所占的实际宽度 px */
const _table_width = ref("");

/** 在没有设定宽度时,可用于撑开剩余宽度的列数 */
let _remainder_col = 0;

/** 固定宽度(包含自定义的宽和最小宽的总和) */
let _fixed_width = 0;

/** 各列最小宽度数组 */
let _min_width_list = [];

/** 表格各列宽度数组 */
let _col_width_list = [];

/** 单列最小宽度 */
const _min_column_width = 80;

初始化表头列表 initColumns

在表格整体渲染结束,能获取 table 实际宽度后,需要执行表头列表初始化,对传入的props中的cols进行处理,计算实际每一列需要width值。

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

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

    // 1. 处理含有固定宽度和最小宽的列

    // 2. 获取各列宽度,并组成一个数组

        // 计算需要自适应的列宽度

    // 3. 输出 columns
}

处理含有固定宽度和最小宽的列

如果含有自定义的宽和最小宽,则需要单独处理这些列,使其不参与剩余宽度自适应当中,同时对应的自适应列的数量也要相应的减去,处理逻辑如下:

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)
}

获取各列宽度,并组成一个数组 getWidthList

这个方法目的返回一个数组,包含各列的宽度值,最后匹配到columns中。 为了不出现列宽过于太小而把内容挤掉的情况,需要判断最小值不能小于设定的80px

/**
 * 获取各列宽度,并组成一个数组
 * @returns Array width_list
 */
function getWidthList() {
    const { cols } = props;
    /** 各列宽度数组 */
    let width_list = [];
    /** 自适应列宽 */
    let adapt_width = getAdaptWidth();
    /**
    * 当表格中含有设置最小宽度的列时,需要挨个比较自适应宽是否小于最小宽度
    * 如果小于,则重新设置各个值并重新计算自适应宽度
    */
    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];

        // 设置成固定宽度
        if (width) { width_list.push(width); continue; }

        // 是否设置成最小宽度:当含有最小宽度属性并且最小宽度大于计算得出的最大列宽
        const hasMinWidth = minWidth && minWidth > adapt_width;
        if (hasMinWidth) { width_list.push(minWidth); continue; }

        // 如果没有定义宽度和最小宽,则设置成自适应宽度或者最小预设宽度
        width_list.push(adapt_width < _min_column_width ? _min_column_width : adapt_width);
    }
    return width_list;
}

计算需要自适应的列宽度 getAdaptWidth

在表格整体渲染结束,能获取 table 实际宽度后,需要计算允许列自适应的宽度有多少,如果所有列都没有设置宽度值,这时候自适应的列宽即为 table 的实际宽度,列宽平均分布就行了。

/**
    * 根据表格实际宽度、已固定的列宽、以及剩余自适应列数,计算得出自适应列宽
    * @returns Number width
    */
    function getAdaptWidth() {
    let width = (_table_width.value - _fixed_width) / _remainder_col;
    return Number(width).toFixed(2);
    }
    ```
    #### 完整代码
    ```javascript
    /**
    * 获取各列宽度,并组成一个数组
    * @returns Array width_list
    */
    function getWidthList() {
    const { cols } = props;

    /** 各列宽度数组 */
    let width_list = [];

    /** 自适应列宽 */
    let adapt_width = getAdaptWidth();

    /**
     * 当表格中含有设置最小宽度的列时,需要挨个比较自适应宽是否小于最小宽度
     * 如果小于,则重新设置各个值并重新计算自适应宽度
     */
    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];

      // 设置成固定宽度
      if (width) { width_list.push(width); continue; }

      // 是否设置成最小宽度:当含有最小宽度属性并且最小宽度大于计算得出的最大列宽
      const hasMinWidth = minWidth && minWidth > adapt_width;
      if (hasMinWidth) { width_list.push(minWidth); continue; }

      // 如果没有定义宽度和最小宽,则设置成自适应宽度或者最小预设宽度
      width_list.push(adapt_width < _min_column_width ? _min_column_width : adapt_width);
    }
    return width_list;
    }

监听屏幕变化和属性更新

触发initColumns的时机有三个

  • 初次加载表格组件
  • 列属性有更新时
  • 屏幕宽度变化时
  watch(() => props.cols, () => { initColumns() });

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

到此这篇关于vue.js Table 组件自定义列宽实现核心方法的文章就介绍到这了,更多相关vue.js Table 组件自定义内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

vue.js Table 组件自定义列宽实现核心方法的更多相关文章

  1. 第七章:table单元格的选择和UIAlertController

    运行app,自己试试选择cell更多关于UIAlertController再继续研究之前,我们需要更多的了解一下UIAlertController。UIAlertController是在iOS8引入用来替代UIAlertView和UIActionSheet的。参照上面的代码片段,我们可以指定UIAlertController的preferredStyle。创建好动作后可以使用addAction将动作和UIAlertController连接起来。这就是使用UIAlertController的方法。

  2. tableview使用自定义类,页面跳转,本地存储

    如图,添加下面的三行代码2下面创建自己的cell,新建一个swift文件,命名为TableViewCell3因为还要考虑到界面的跳转,需要新建swift文件PushTest

  3. Swift UITableView相关功能八

    但是,我们发现当我们点击右侧索引的时候好像和table的关系不明确。其实我们少了一个代理方法,他是专门用来关联索引和table分区的这里我们简单设置了一下,将字母顺序和table的分区对应上了。

  4. Swift设置Table View的Cell中Lable自适应内容高度的

    Swift设置TableView的Cell中Lable自适应内容高度的最后修改在TableCell中Label的lines属性,将其设置为0。

  5. 更加 Swift 化的 Collection View 和 Table View Cells

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  6. 制作一个可以滑动操作的 Table View Cell

    本教程将会向你展示如何制作一个这样的TableViewCell,而不用因嵌套的ScrollView陷入困境。如果你还不知道一个可滑动的TableViewCell意味着什么,那么看看Apple的邮件应用:可能你会想,既然Apple展示了这种方案,那它应该已将其开放给开发者使用了。这会要求你深入研究iOS7UITableViewCell的结构,以便复制出我们需要的行为。打开MasterViewController.m并找到viewDidLoad。这个循环添加了一些字符串到_objects数组,应用运行时,这些

  7. 如何实现可收起和展开的Table Section

    如何实现可收起和展开的TableSection这是一个简单的iOSswift项目,旨在介绍如何实现可收起和展开的tablesection,并且,项目不需要mainstoryboard,XIB,注册nib等,只需要纯的Swfit代码!切换收起和展开的函数如下:注意到我们不是简单的重绘整个section,实际上我们只需要重绘section里的所有cell就好,这样做的好处是避免了sectionheader因重绘时闪烁的效果,最重要是的可以让我们更平滑地处理我们想要的动画效果,例如旋转那个箭头,改变背景颜色等等

  8. Swift iOS: UITableView的使用

    Table继承于UITableView,并实现UITableViewDataSource,UITableViewDelegate,在配合代码:就指明了UITableView的数据源对象为Table,委托对象也是Table。前者指明此对象是UITableView的数据提供者,后者指明此对象是UITableView的外观和行为的提供者。添加删除修改类UITableView不但可以显示内容,还可以配合很多操作。标记类UITableView支持对每个行做标记和取消标记,标记可以有多种。可以通过官方手册查询UITa

  9. android – SQLiteDatabase – 如何使用where子句?

    例如,如果我想要TIMetaBLE_MODULECODE=123.我将如何做到这一点,我已经读过它的第一个null.我在下面尝试了这个,但仍然无法正常工作解决方法TABLE_ROW_ID“=”rowID,这里“=”是where子句

  10. android – 为什么我们需要onUpgrade(); SQLiteOpenHelper类中的方法

    我正在遵循这个教程可以任何身体请让我清楚这段代码.问题onUpgrade()的目的是什么;方法?重要为什么我们在这个方法中删除表并重新创建?提前致谢.解决方法onUpgrade基本上用于处理任何新版本应用程序的新数据库更改.在onUpgrade中并不总是需要删除表,这取决于您的用例.如果要求不要保留旧版本应用程序中的数据,那么drop应该会有所帮助,但是如果它更改架构那么它应该只有更改脚本.

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部