# vue-mobile-table

## 说明
`vue-mobile-table`是一个移动端使用的轻量级table展示组件（目前对增删改并不支持，主要针对类似股票软件中查看行情的table展示列表的业务场景），组件内部布局主要采用flex布局，并未使用table标签。内部在滚动上使用`BetterScroll 2.0`中的`transform`来处理滚动，使得滚动更加细腻。在dom渲染上采用虚拟dom技术，让`vue-mobile-table`很好的保证不卡顿的前提下渲染一个超长的列表。并且`vue-mobile-table`支持上拉加载和下拉刷新，更加方便做多样的ajax请求。该组件高度默认为父组件高度，且表头固定（可通过设置父组件高度来控制该组建的高度）。

## 功能
1. 表头固定
2. 表列左边固定
3. 虚拟渲染（默认且一定开启）
4. 上拉加载和下拉刷新
5. 支持排序


## 优点
1. 可渲染大量数据，并保持流畅
2. 使用betterscroll 2.0 替换原生滚动，在移动端滚动更加流畅
3. 支持排序
4. 所有设置为纯数字的关于元素大小的单位都将根据标准设计图的px转为当前对应设备的vw单位
## 缺陷
1. 并不支持增删改等一些列操作
2. 只能针对固定行高的展示列表，对非固定行高的列表，
3. 固定列只支持左固定
## 样式兼容性
该组件样式主要使用flex布局，和fit-content，并无其他非常规css样式
## 使用
+ 安装组件
```
npm install vue-mobile-table --save
```
+ main.js中引入该组件
```js
import vueMobileTable from  from 'vue-mobile-table'
Vue.use(vueMobileTable)
```
+ 使用
```html
<template>
  <div
    style="height: 100%; width: 100%; overflow: hidden; box-sizing: border-box"
  >
    <vue-mobile-table :dataSource="tableData" :requestData="requestData">
      <table-column
        prop="index"
        fixed
        label="序号"
        sortable
      ></table-column>
      <table-column
        prop="name"
        label="名称"
        min-width="120"
        align="right"
      ></table-column>
      <table-column prop="text" label="文本" min-width="120"></table-column>
      <table-column prop="age" label="年龄" min-width="120"></table-column>
    </vue-mobile-table>
  </div>
</template>

<script>
export default {
  name: "testPage",
  data() {
    return {
      tableData: [],
    };
  },
  methods: {
    requestData(isFresh) {
      // alert(12)
      return new Promise((reslove) => {
        if (isFresh) {
          setTimeout(() => {
            reslove(true);
          }, 2000);
        } else {
          setTimeout(() => {
            for (let index = 0; index < 100; index++) {
              this.tableData.push({
                index: index,
                age: index,
                text: "我是一段文字，我很长，不要换行",
                name: "姓名" + index + "号",
              });
            }
            reslove(true);
          }, 2000);
        }
      });
    },
  },
  created() {
    let data = [];
    for (let index = 0; index < 100; index++) {
      data.push({
        index: index,
        age: index,
        text: "我是一段文字，我很长，不要换行",
        name: "姓名" + index + "号",
      });
    }
    this.tableData = data;
    // console.log(this.tableData);
  },
};
</script>

<style></style>

```

示例视频demo
<iframe height=498 width=510 src="https://www.bilibili.com/video/BV1hG4y1q79a/?vd_source=20f59a0a89f5601ed6325f824228065f"/>


## props
| 属性                 |类型       | 默认值| 含义   |
|  ----               | ----      |----|----    |
| dataKey             | String    | '' | 每一行的key对应的property，目前并没有用处，不排除以后版本迭代后使用 |
| dataSource          | Array     | [] | 数据源 |
| itemHeight          | Number    | 60 | 每一行的高度，(会自动根据当前设备转为vw，可以按照标准设计图高度px进行设定) |
| defaultFixItemWidth | String    |30vw| 默认固定列宽度，建议给固定列设置一个宽度，而不是使用该属性默认值 |
| requestData         | Function  |    | 滚动加载时请求接口的函数，返回一个promise，包含一个参数isRefresh:是否下拉刷新 |
| loadingComplete     | Boolean   |false| 请求数据后是否加载完，如果设置为true，后面的滚动到底部将不会触发requestData函数 |
| paddingConfig       | Object    |{LRPadding: 10}| LRPadding：默认头部和内容的两侧的padding大小 |
| borderConfig        | Object    |{  innerBorder: true,color: "#e8eaec",borderType: "solid",headerBorder: true,}| color：边框颜色，borderType：边框类类型，headerBorder：是否开启表头下边框 |
| sortableConfig        | Object    |{  iconSize: 5,color: "#ccc",activeColor: "#409eff"}| color：排序icon默认颜色，activeColor：排序icon激活颜色，iconSize：排序icon大小 |

## event
| 事件                 |参数       | 含义   |
|  ----               | ----      |   ----  |
|  sortChangeEvent    | (sortType,sortField)|点击了表头字段，产生了排序事件，需要开启在table-column中开启sortable,sortType:排序的方式（asc,desc,''）；sortField：排序的字段|
## slot
目前不支持插槽
table-column插槽使用同el-table

示例：
```html
  <table-column prop="age" label="年龄" min-width="120">
    <template #default={row}>
      <span>{{row.age}}</span>
    </template>
  </table-column>
```


## 附加 table-column插槽
### props
props: ['label', 'prop', 'width', "fixed", 'sortable', 'minWidth', 'align']；
其中label表示表头标题，prop为该列对应的字段属性名称，sortable为是否开启排序，align可选值为left，center，right。
基本使用与el-table中的el-table-column一致

## 巧用该组件
借用上拉加载和下拉刷新的功能一次排序事件，我们可以再次封装对本组件做一个移动端滚动分页的效果，并支持排序,甚至定时更新table数据的功能

注意：本示例只是提供一个思路，具体扩展请根据业务场景调整
示例：
```html
<template>
  <vue-mobile-table :dataSource="dataSource" :requestData="requestData" @sortChangeEvent="sortChangeEvent" :itemHeight="60" :loadingComplete="loadingComplete">
    <template v-for="(index, name) in $slots" :slot="name">
      <slot :name="name" />
    </template>
  </vue-mobile-table>
</template>

<script>
export default {
  props: {
    loadData: {
      type: Function,
      default: () => {},
    },
    defaultSortField: {
      type: String,
      default: "",
    },
    defaultSortType: {
      type: String,
      default: "desc",
    },
  },
  data() {
    return {
      firstInto: true,
      dataSource: [],
      page: 1,
      size: 20,
      sortType: "",
      sortField: "",
      loadingComplete: false,
    };
  },
  methods: {
    sortChangeEvent(sortType, sortField) {
      this.sortType = sortType;
      this.sortField = sortField;
      if (this.sortType === "") this.sortField = "";
      // 保持页面参数不变
      this.httpData();
    },
    requestData(isFresh) {
      if (isFresh) {
        this.resetPage();
      }
      return this.httpData(true);
    },
    // 初次加载数据，更新数据，
    httpData(loading = false) {
      return new Promise((resolve, reject) => {
        // 上拉加载数据
        this.loadData(this.page, this.size, this.sortField, this.sortType, this.searchVal)
          .then((res) => {
            this.dataSource.push(...res);
            this.loadingComplete = this.dataSource.length < this.page * this.size; // 是否加载完毕
            if (loading) {
              this.page += 1;
            }
            resolve(true);
          })
          .catch((err) => reject(err));
      });
    },
    resetPage() {
      this.page = 1;
      this.size = 20;
    },
    init() {
      this.sortType = this.defaultSortType;
      this.sortField = this.defaultSortField;;
    },
  },
  mounted() {},
  created() {
    this.init();
  },
};
</script>

<style lang="less" scoped></style>
```

## 未来规划
本组件为开发项目过程中所需创建，目前可定制化内容不是很多，很多默认内容是根据本项目ui设计图进行的默认配置。之后将加入更多客制化内容，开放更多插槽的定义以及可定制化props，更多的event，更多的内置方法。对于目前不支持的功能，如有需要，小伙伴可前往github clone源码[vue-mobile-table](https://gitee.com/zhou-linfeng/vue-mobile-table)后自行修改扩展。

## 建议
在项目中使用该组件，建议另外针对当前项目对该组件再次进行封装。目前该组件发布迭代较慢，表格样式并不是高度可定制化的，如果遇到不能定制化样式的时候，请使用 vue的深度选择器deep在项目中手动更改样式


