iview-设置table高度100的一种方法

6次阅读

共计 2340 个字符,预计需要花费 6 分钟才能阅读完成。

运行环境

iview 版本: 3.5.0-rc.1 
vue 版本: 2.6.10 

问题


iview 中的 table 是不能直接占满父容器的,它的 height 属性必须设置成一个固定值。假如直接给 table 设置 style 为
height:100% , 它的滚动条会丢失。

但是很多时候我们需要 table 占满父容器,需要表头和页脚进行固定,只让中间数据部分进行滚动。

chrome 中打开 Elements , 可以看到 iview 使用了 object 标签。html 中一般只能监听 window 的 resize 事件,而无法直接监听 div 等元素大小改变的,但是有时可以插入一个 object 标签来间接监听 div 大小的改变。它这里是否用了 object 来监听大小改变呢?

打开 iview 的源码 , 看到它果真是用来监听大小改变的,但是它监听改变后只处理了 width,没有处理 height。所以这里我们可以包装一下 Table, 监听它的 resize 事件,然后动态设置 height 属性,来使 Table 支持 height:100%

解决方法

iview 是用的 element-resize-detector 库来监听外层 div 的改变,并且把将这个库设置为组件的全局变量。所以我们也可以使用这个全局变量来监听外层 div 大小,然后动态设置 height。

创建一个 FillTable 的组件,用来包装 Table, FillTable.js 的源码如下:

FillTable

import {Table} from 'iview';
export default {
  name: 'fill-table',
  render(h) {
    /** 传递 prop */
    const tableProps = {};
    for (let prop in Table.props) {tableProps[prop] = this[prop];
    }
    tableProps.height = this.tableHeight;

    return h(Table, {
      props: tableProps,
      ref: 'table',
      /** 传递事件 */
      on: this.$listeners,
      /** 传递作用域插槽 */
      scopedSlots: this.$scopedSlots,
      /** 传递插槽 */
      slot: this.$slot
    });
  },
  props: (() => {var props = {};
    Object.assign(props, Table.props, {
      height: {type: Number},
      /** 默认占满父容器 */
      fill: {
        type: Boolean,
        default: true
      }
    });
    return props;
  })(),
  watch: {
    height: {handler() {this.tableHeight = this.height;}
    },
    immediate: true
  },
  data() {
    // 自带属性值
    return {tableHeight: 0};
  },
  methods: {handleIViewTableResize(el) {this.tableHeight = el.offsetHeight;},
    getTableRef() {return this.$refs.table;}
  },
  mounted() {if (this.fill) {// this.$nextTick(() => {this.getTableRef().observer.listenTo(this.$el, this.handleIViewTableResize);
      // });
    }
    /** 传递方法 */
    for (let method in Table.methods) {this[method] = (...args) => Table.methods[method].apply(this.getTableRef(), args);
    }
  },

  beforeDestroy() {if (this.fill) {this.getTableRef().observer.removeListener(this.$el, this.handleIViewTableResize);
    }
  }
};

使用

使用时和 iview 中的 table 的属性和方法基本一致,只有以下地方需要注意:

  • 添加 v-bind:fill 属性, 默认值是 true,为 true 请不要再设置 v -bind:height。设置为 true,则支持 table 的 style 中的 height:100% 的样式。
  • 假如需要 v-bind:height= 固定值,则需要 v-bind:fill="false" 
  • 假如需要找到 table 组件实例,请使用 getTableRef 方法,如 this.refs.table.getTableRef()
      <FillTable
        ref="table"
        style="width:100%;height:100%"
        :columns="columns1"
        :data="data1"
        :fill="true"
      >
        <template #name="{row}">
          <strong>{{row.name}}--ddd</strong>
        </template>
      </FillTable>

注意事项

由于是侵入性修改,假如 iview 改了源码,比如将 observer 的全局字段去除了,则这里就会出错。这时可以直接引用 element-resize-detector 来监听 Table 的大小改变。

demo


在线运行: https://meteor199.github.io/my-demo/vue/iview-fill-table/dist/index.html
demo 源码:https://github.com/meteor199/my-demo/tree/master/vue/iview-fill-table

正文完
 0