element-ui表格的二次封装

4,665 阅读6分钟

在使用element-ui的时候,虽然说element官方的el-table组件已经相当好了,但针对的是所以群体,如果我们在写后台系统的时候希望更多的去封装已减少重复劳动。这次趁自己在写后台系统的时间来具体记录下如何去封装的。

分析element-ui官方的el-table组件

表格属性

首先需要分析出那些属性是项目中必须每次都需要的,这种属性适合默认值,如果不是必须的但又用到了的可以作为可配置项。根据自己的项目其实最常用的属性data、stripe,其它的属性大家可以根据自己的项目视具体情况而定。

表格方法

方法中在目前的项目中是没有使用到的,但是有一个应该是会有人用到的,sort-change

表格项的属性

表格的每一项的属性应该是最多的了,毕竟需要配置的也就是表格的每一项了,主要有label、prop、width、fixed、sortable、formatter、show-overflow-tooltip,其实这里根据自己的项目还需要加一个是否为图片的属性,毕竟表格里面显示图片还是显示不下的需要使用其他组件来显示图片,暂定属性为isImg。

表格操作按钮

通常后台系统最后一列都需要一个操作,毕竟有很多数据时需要人工进行操作的,所以需要添加一些操作的按钮来对某一行数据进行操作。

定义想象的数据模型

根据上面的分享接下来我们先把需要的数据或则是配置项定义下来,这样后面定义组件的时候就可以根据定义的数据或则配置项来生成表格的内容。

表格数据的属性

根据上面的分享表格数据的属性就两个data和stripe,这里需要外加一个loading,所以结构就像下面这样的:

<template>
  <div class="home">
      test
  </div>
</template>

<script>

export default {
  name: "home",
  data() {
    return {
      table: {
        stripe: false, //是否为斑马纹
        loading: false, // 数据加载loading
      }
    };
  },
  mounted() {}
};
</script>

目前没有数据所以可以先关闭loading和stripe

接下来就是最重要的数据了,目前没有接口所以这里使用自己手动添加数据,也就是在table对象中添加data这样一个数组来保存表格的数据,如下:

data() {
    return {
      table: {
        stripe: false, //是否为斑马纹
        loading: false, // 数据加载loading
        data: [
          {
            date: "2016-05-02",
            name: "王小虎",
            address: "上海市普陀区江路 1518 弄"
          },
          {
            date: "2016-05-04",
            name: "王小虎",
            address: "上海市普陀区江路 1517 弄"
          },
          {
            date: "2016-05-01",
            name: "王小虎",
            address: "上海市普陀区江路 1519 弄"
          },
          {
            date: "2016-05-03",
            name: "王小虎",
            address: "上海市普陀区江路 1516 弄"
          }
        ]
      }
    };
  }

这样表格的属性也就差不多了。

表格的方法

表格的方法也就一个就是排序的,因项目中没有用到所以这里只是提供一个思路,具体实现的细节大家可以自己去补充,在table对象里面新添加一个event配置项如下:

event: {
	sortEvent: this.tableSort
}

这里的tableSort就不具体写了,大家可以自己参考element-ui官方来写这个排序的查询。

表格每一项数据的属性

这个也是重点需要配置的,先定义几组数据模型,也就是在table对象中添加一个数组header用于表格的生成,如下:

header: [
          {
            prop: "selection",
            width: "55"
          },
          {
            prop: "date",
            label: "日期11"
          },
          {
            prop: "date",
            label: "日期11",
            width: "180",
            formatter: "",
            tooltip: false,
            sortable:false,
            fixed: "right"
          },
          {
            prop: "date",
            label: "日期11",
            width: "180",
            formatter: "",
            tooltip: false,
            sortable:false,
            isImg:false,
            fixed: "right"
          },
          {
            prop: "options",
            label: "操作",
            width: "180",
            fixed: "right"
          }
        ]

数组中第一个和最后一个位置最好不要动,第一个是多选操作,最后一个是操作栏

表格数据的操作按钮

有了操作栏那么就需要有操作的按钮,先定义一个试试看,如下:

options: [
          {
            type: "success",
            label: "通过",
            event: this.submitBtn,
            isShow: item => {
              return item.status == 0 ? false : true;
            }
          }
        ]

isShow为什么时候显示该按钮,这里有一个回调来配置,需要返回一个布尔值

表格组件的定义

表格的基础数据定义好了就可以开始定义表格组件了,新建一个table组件,然后添加如下代码:

<template>
  <el-table :data="table.data" v-loading="table.loading" :stripe="table.stripe">
      
  </el-table>
</template>

<script>
export default {
  props: {
    table: Object
  }
};
</script>

这时候是看不到任何效果的,所以先在页面中引入该组件(上面生成数据的页面中),接下来就是生成表格的内容了。

生成多选操作

多选操作在配置的时候就是prop的值为selection,所以直接在循环中判断即可,如下:

<template v-for="item in table.header">
        <el-table-column type="selection" :width="item.width" v-if="item.prop == 'selection'"></el-table-column>
</template>

效果如下:

生成列表项

列表项就是具体的表格项属性了,配置好基本上表格的数据也就能看到了,这里就不单个去说了,直接看最终代码吧:

<template>
  <el-table :data="table.data" v-loading="table.loading" :stripe="table.stripe">
    <template v-for="item in table.header">
      <el-table-column type="selection" :width="item.width" v-if="item.prop == 'selection'"></el-table-column>
      <template v-else-if="item.prop == 'options'">
        <template v-if="table.options.length">
          <el-table-column :label="item.label" :width="item.width" :fixed="item.fixed">
            <template slot-scope="scope">
              <template v-for="btn in table.options">
                <el-button
                  :type="btn.type"
                  v-if="btn.isShow ? btn.isShow(scope.row) : true"
                  @click="btn.event(scope.row)"
                >{{btn.label}}</el-button>
              </template>
            </template>
          </el-table-column>
        </template>
      </template>
      <template v-else>
        <template v-if="item.isImg">
          <el-table-column :prop="item.prop" :label="item.label" :width="item.width">
            <template slot-scope="scope">
              <el-popover placement="left" trigger="click">
                <div>
                  <el-image
                    style="width: 300px; height: auto;"
                    :src="scope.row[item.prop]"
                    fit="contain"
                    slot="reference"
                  ></el-image>
                </div>
                <el-image
                  style="width: 100px;height: 100px;"
                  :src="scope.row[item.prop]"
                  fit="contain"
                  slot="reference"
                ></el-image>
              </el-popover>
            </template>
          </el-table-column>
        </template>
        <el-table-column
          :prop="item.prop"
          :label="item.label"
          :width="item.width"
          :formatter="item.formatter?item.formatter:null"
          :show-overflow-tooltip="item.tooltip?item.tooltip:false"
          :sortable="item.sortable?item.sortable:false"
          v-else
        ></el-table-column>
      </template>
    </template>
  </el-table>
</template>

<script>
export default {
  props: {
    table: Object
  }
};
</script>

修改初始数据

这个时候基本封装好了,对于刚开始的初始数据做如下修改即可:

<template>
  <div class="home">
    <my-table :table="table"></my-table>
  </div>
</template>

<script>
import myTable from "@/components/Table";

export default {
  name: "home",
  components: {
    "my-table": myTable
  },
  data() {
    return {
      table: {
        stripe: false, //是否为斑马纹
        loading: false, // 数据加载loading
        data: [
          {
            date: "2016-05-02",
            name: "王小虎",
            img:
              "https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg",
            address: "上海市普陀区江路 1518 弄"
          },
          {
            date: "2016-05-04",
            name: "王小虎",
            img:
              "https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg",
            address: "上海市普陀区江路 1517 弄"
          },
          {
            date: "2016-05-01",
            name: "王小虎",
            img:
              "https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg",
            address: "上海市普陀区江路 1519 弄"
          },
          {
            date: "2016-05-03",
            name: "王小虎",
            img:
              "https://fuss10.elemecdn.com/1/34/19aa98b1fcb2781c4fba33d850549jpeg.jpeg",
            address: "上海市普陀区江路 1516 弄"
          }
        ],
        event: {
          sortEvent: this.tableSort
        },
        header: [
          {
            prop: "selection",
            width: "55"
          },
          {
            prop: "date",
            label: "日期11",
            width: "180",
            formatter: ""
          },
          {
            prop: "name",
            label: "名称",
            tooltip: false,
            sortable: false
          },
          {
            prop: "img",
            label: "头像",
            width: "180",
            isImg: true
          },
          {
            prop: "address",
            label: "地址",
            width: "180",
            tooltip: true
          },
          {
            prop: "options",
            label: "操作",
            width: "200",
            fixed: "right"
          }
        ],
        options: [
          {
            type: "success",
            label: "通过",
            event: this.checkPass,
            isShow: item => {
              return item.status == 0 ? false : true;
            }
          },
          {
            type: "danger",
            label: "不通过",
            event: this.checkNoPass,
            isShow: item => {
              return item.status == 1 ? false : true;
            }
          }
        ]
      }
    };
  },
  methods: {
    tableSort(val) {
      console.log(val);
    },
    checkPass(val) {
      console.log(val);
    },
    checkNoPass(val) {
      console.log(val);
    }
  }
};
</script>

效果如下: